diff --git a/haddock-api.cabal b/haddock-api.cabal
--- a/haddock-api.cabal
+++ b/haddock-api.cabal
@@ -1,10 +1,10 @@
-cabal-version:        2.0
+cabal-version:        3.0
 name:                 haddock-api
-version:              2.26.0
+version:              2.27.0
 synopsis:             A documentation-generation tool for Haskell libraries
 description:          Haddock is a documentation-generation tool for Haskell
                       libraries
-license:              BSD2
+license:              BSD-2-Clause
 license-file:         LICENSE
 author:               Simon Marlow, David Waern
 maintainer:           Alec Theriault <alec.theriault@gmail.com>, Alex Biehl <alexbiehl@gmail.com>, Simon Hengel <sol@typeful.net>, Mateusz Kowalczyk <fuuzetsu@fuuzetsu.co.uk>
@@ -13,7 +13,7 @@
 copyright:            (c) Simon Marlow, David Waern
 category:             Documentation
 build-type:           Simple
-tested-with:          GHC==9.2.*
+tested-with:          GHC==9.4.*
 
 extra-source-files:
   CHANGES.md
@@ -44,10 +44,11 @@
 
   -- this package typically supports only single major versions
   build-depends: base            ^>= 4.16.0
-               , ghc             ^>= 9.2
+               , ghc             ^>= 9.4
                , ghc-paths       ^>= 0.1.0.9
-               , haddock-library ^>= 1.9.0
+               , haddock-library ^>= 1.11
                , xhtml           ^>= 3000.2.2
+               , parsec          ^>= 3.1.13.0
 
   -- Versions for the dependencies below are transitively pinned by
   -- the non-reinstallable `ghc` package and hence need no version
@@ -93,6 +94,8 @@
     Haddock.Parser
     Haddock.Utils
     Haddock.Utils.Json
+    Haddock.Utils.Json.Types
+    Haddock.Utils.Json.Parser
     Haddock.Backends.Xhtml
     Haddock.Backends.Xhtml.Decl
     Haddock.Backends.Xhtml.DocMarkup
@@ -169,17 +172,20 @@
     Haddock.Types
     Haddock.Utils
     Haddock.Utils.Json
+    Haddock.Utils.Json.Types
+    Haddock.Utils.Json.Parser
     Haddock.Version
     Paths_haddock_api
     Haddock.Backends.Hyperlinker.ParserSpec
     Haddock.Backends.Hyperlinker.Parser
     Haddock.Backends.Hyperlinker.Types
 
-  build-depends: ghc             ^>= 9.2
+  build-depends: ghc             ^>= 9.4
                , ghc-paths       ^>= 0.1.0.12
-               , haddock-library ^>= 1.9.0
+               , haddock-library ^>= 1.11
                , xhtml           ^>= 3000.2.2
-               , hspec           ^>= 2.8
+               , hspec           ^>= 2.9
+               , parsec          ^>= 3.1.13.0
                , QuickCheck      >= 2.11  && ^>= 2.14
 
   -- Versions for the dependencies below are transitively pinned by
@@ -199,7 +205,7 @@
                , transformers
 
   build-tool-depends:
-    hspec-discover:hspec-discover ^>= 2.8
+    hspec-discover:hspec-discover ^>= 2.9
 
 source-repository head
   type:     git
diff --git a/resources/html/Linuwial.std-theme/linuwial.css b/resources/html/Linuwial.std-theme/linuwial.css
--- a/resources/html/Linuwial.std-theme/linuwial.css
+++ b/resources/html/Linuwial.std-theme/linuwial.css
@@ -544,6 +544,10 @@
   background: url(synopsis.png) no-repeat -75px -8px;
 }
 
+#synopsis details:not([open]) > ul {
+  visibility: hidden;
+}
+
 #synopsis ul {
   height: 100%;
   overflow: auto;
diff --git a/resources/html/haddock-bundle.min.js b/resources/html/haddock-bundle.min.js
--- a/resources/html/haddock-bundle.min.js
+++ b/resources/html/haddock-bundle.min.js
@@ -1,2 +1,2 @@
-!function i(s,a,l){function c(t,e){if(!a[t]){if(!s[t]){var n="function"==typeof require&&require;if(!e&&n)return n(t,!0);if(u)return u(t,!0);var o=new Error("Cannot find module '"+t+"'");throw o.code="MODULE_NOT_FOUND",o}var r=a[t]={exports:{}};s[t][0].call(r.exports,function(e){return c(s[t][1][e]||e)},r,r.exports,i,s,a,l)}return a[t].exports}for(var u="function"==typeof require&&require,e=0;e<l.length;e++)c(l[e]);return c}({1:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.setCookie=function(e,t){document.cookie=e+"="+encodeURIComponent(t)+";path=/;"},n.clearCookie=function(e){document.cookie=e+"=;path=/;expires=Thu, 01-Jan-1970 00:00:01 GMT;"},n.getCookie=function(e){for(var t=e+"=",n=document.cookie.split(";"),o=0;o<n.length;o++){for(var r=n[o];" "==r.charAt(0);)r=r.substring(1,r.length);if(0==r.indexOf(t))return decodeURIComponent(r.substring(t.length,r.length))}return null}},{}],2:[function(e,t,n){"use strict";var o,r=this&&this.__extends||(o=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},function(e,t){function n(){this.constructor=e}o(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)});Object.defineProperty(n,"__esModule",{value:!0});var i,s,a=e("preact"),l=a.h,c=a.Component;(s=i||(i={}))[s.Closed=0]="Closed",s[s.Open=1]="Open";var u={defaultInstanceState:i.Open,rememberToggles:!0},d=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return r(t,e),t.prototype.render=function(t){return l("li",null,l("a",{href:"#",onClick:function(e){e.preventDefault(),t.onClick()}},t.title))},t}(c);function h(e){var t=document.querySelector("#page-menu"),n=document.createElement("li");t.insertBefore(n,t.firstChild),a.render(l(d,{onClick:e,title:"Instances"}),t,n)}var p=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return r(t,e),t.prototype.componentWillMount=function(){var t=this;document.addEventListener("mousedown",this.hide.bind(this)),document.addEventListener("keydown",function(e){t.state.isVisible&&"Escape"===e.key&&t.hide()})},t.prototype.hide=function(){this.setState({isVisible:!1})},t.prototype.show=function(){this.state.isVisible||this.setState({isVisible:!0})},t.prototype.toggleVisibility=function(){this.state.isVisible?this.hide():this.show()},t.prototype.componentDidMount=function(){this.props.showHideTrigger(this.toggleVisibility.bind(this))},t.prototype.render=function(e,t){return l("div",{id:"preferences",class:t.isVisible?"":"hidden"},l("div",{id:"preferences-menu",class:"dropdown-menu",onMouseDown:function(e){e.stopPropagation()}},l(b,null)))},t}(c);function f(){var e=JSON.stringify(u);try{localStorage.setItem("global",e)}catch(e){}}var v=!1;function g(){if(!v){v=!0;var e=localStorage.getItem("global");if(e)try{var t=JSON.parse(e);u.defaultInstanceState=t.defaultInstanceState,u.rememberToggles=t.rememberToggles}catch(e){if(!(e instanceof SyntaxError||e instanceof TypeError))throw e;localStorage.removeItem("global")}}}function m(t){return function(e){u.defaultInstanceState=t,A(),f(),E(),O()}}function y(e){var t=e.target.checked;u.rememberToggles=t,f(),E(),O()}function _(e){var t=document.getElementById("default-collapse-instances");null!==t&&(t.checked?m(i.Closed)(e):m(i.Open)(e))}function b(){return g(),l("div",null,l("div",null,l("button",{type:"button",onClick:j},"Expand All Instances"),l("button",{type:"button",onClick:P},"Collapse All Instances")),l("div",null,l("input",{type:"checkbox",id:"default-collapse-instances",name:"default-instance-state",checked:u.defaultInstanceState===i.Closed,onClick:_}),l("span",null,"Collapse All Instances By Default")),l("div",null,l("input",{type:"checkbox",id:"remember-toggles",name:"remember-toggles",checked:u.rememberToggles,onClick:y}),l("label",{for:"remember-toggles"},"Remember Manually Collapsed/Expanded Instances")))}var k={};function S(e){var t=k[e];if(null==t)throw new Error("could not find <details> element with id '"+e+"'");return t}function x(){return u.defaultInstanceState==i.Open}function w(e){for(var t=S(e.target.id),n=t.element.open,o=0,r=t.toggles;o<r.length;o++){var i=r[o];i.classList.contains("details-toggle-control")&&(i.classList.add(n?"collapser":"expander"),i.classList.remove(n?"expander":"collapser"))}}function C(e){var t=e.getAttribute("data-details-id");if(!t)throw new Error("element with class "+e+" has no 'data-details-id' attribute!");return t}function L(e){var t=S(C(e)).element;t.open=!t.open}var M="local-details-config:";function I(){return M+document.location.pathname}function E(){for(var e=[],t=0;t<localStorage.length;++t){var n=localStorage.key(t);null!==n&&n.startsWith(M)&&e.push(n)}e.forEach(function(e){localStorage.removeItem(e)})}function O(){if(u.rememberToggles){var e=Array.prototype.slice.call(document.getElementsByClassName("instances details-toggle details-toggle-control")),n=[];e.forEach(function(e){var t=C(e);document.getElementById(t).open!=x()&&n.push(t)});var t=JSON.stringify(n);try{localStorage.setItem(I(),t)}catch(e){}}}function A(){switch(u.defaultInstanceState){case i.Closed:N(!0);break;case i.Open:N(!1)}}function T(e){e.preventDefault(),L(e.currentTarget),O()}function N(o){var e=document.getElementsByClassName("subs instances");[].forEach.call(e,function(e){var t=o?"collapser":"expander",n=e.getElementsByClassName("instances "+t)[0];n&&L(n)})}function P(){N(!0),O()}function j(){N(!1),O()}n.init=function(e){!function(){for(var e=0,t=Array.prototype.slice.call(document.getElementsByTagName("details"));e<t.length;e++){var n=t[e];"string"==typeof n.id&&0<n.id.length&&(k[n.id]={element:n,toggles:[]},n.addEventListener("toggle",w))}}(),Array.prototype.slice.call(document.getElementsByClassName("details-toggle")).forEach(function(e){var t=S(C(e));t.toggles.push(e),e.addEventListener("click",T),e.classList.contains("details-toggle-control")&&e.classList.add(t.element.open?"collapser":"expander")}),function(){if(g(),A(),u.rememberToggles){var e=localStorage.getItem(I());if(e)try{JSON.parse(e).forEach(function(e){S(e).element.open=!x()})}catch(e){if(!(e instanceof SyntaxError||e instanceof TypeError))throw e;localStorage.removeItem(I())}}}(),a.render(l(p,{showHideTrigger:e||h}),document.body)}},{preact:7}],3:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var o,r=e("./style-menu"),i=e("./details-helper"),s=e("./quick-jump");o=function(){document.body.classList.add("js-enabled"),r.init(),s.init(),i.init()},"interactive"===document.readyState?o():document.addEventListener("readystatechange",function(){"interactive"===document.readyState&&o()})},{"./details-helper":2,"./quick-jump":4,"./style-menu":5}],4:[function(e,t,n){"use strict";var o,r=this&&this.__extends||(o=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},function(e,t){function n(){this.constructor=e}o(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)});Object.defineProperty(n,"__esModule",{value:!0});var i=e("fuse.js"),s=e("preact"),a=s.h,l=s.Component;var c=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return r(t,e),t.prototype.render=function(t){return a("li",null,a("a",{href:"#",onClick:function(e){e.preventDefault(),t.onClick()}},t.title))},t}(l);function u(e){var t=document.querySelector("#page-menu"),n=document.createElement("li");t.insertBefore(n,t.firstChild),s.render(a(c,{onClick:e,title:"Quick Jump"}),t,n)}function d(e,t){return t.length<=e?t:t.slice(0,e)}var h=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.linkIndex=0,e.focusPlease=!1,e.navigatedByKeyboard=!1,e}return r(e,t),e.prototype.componentWillMount=function(){var e,t,n,o,r=this;this.setState({searchString:"",isVisible:!1,expanded:{},activeLinkIndex:-1,moduleResults:[]}),e=this.props.baseUrl+"/doc-index.json",t=function(e){r.setState({fuse:new i(e,{threshold:.25,caseSensitive:!0,includeScore:!0,tokenize:!0,keys:[{name:"name",weight:.7},{name:"module",weight:.3}]}),moduleResults:[]})},n=function(e){console&&console.error("could not load 'doc-index.json' for searching",e),r.setState({failedLoading:!0})},(o=new XMLHttpRequest).onreadystatechange=function(){if(o.readyState===XMLHttpRequest.DONE)if(200===o.status){if(t)try{t(JSON.parse(o.responseText))}catch(e){n(o)}}else n&&n(o)},o.open("GET",e,!0),o.send(),document.addEventListener("mousedown",this.hide.bind(this)),document.addEventListener("keydown",function(e){r.state.isVisible&&("Escape"===e.key?r.hide():"ArrowUp"===e.key||"k"===e.key&&e.ctrlKey?(e.preventDefault(),r.navigateLinks(-1)):"ArrowDown"===e.key||"j"===e.key&&e.ctrlKey?(e.preventDefault(),r.navigateLinks(1)):"Enter"===e.key&&0<=r.state.activeLinkIndex&&r.followActiveLink()),"s"===e.key&&"input"!==e.target.tagName.toLowerCase()&&(e.preventDefault(),r.show())})},e.prototype.hide=function(){this.setState({isVisible:!1,searchString:""})},e.prototype.show=function(){this.state.isVisible||(this.focusPlease=!0,this.setState({isVisible:!0,activeLinkIndex:-1}))},e.prototype.toggleVisibility=function(){this.state.isVisible?this.hide():this.show()},e.prototype.navigateLinks=function(e){var t=Math.max(-1,Math.min(this.linkIndex-1,this.state.activeLinkIndex+e));this.navigatedByKeyboard=!0,this.setState({activeLinkIndex:t})},e.prototype.followActiveLink=function(){this.activeLinkAction&&this.activeLinkAction()},e.prototype.updateResults=function(){var e=this.input&&this.input.value||"",t=this.state.fuse.search(e),o={};t.forEach(function(e){var t=e.item.module;(o[t]||(o[t]=[])).push(e)});var r=[],n=function(e){var t=o[e],n=0;t.forEach(function(e){n+=1/e.score}),r.push({module:e,totalScore:1/n,items:t})};for(var i in o)n(i);r.sort(function(e,t){return e.totalScore-t.totalScore}),this.setState({searchString:e,isVisible:!0,moduleResults:r})},e.prototype.componentDidUpdate=function(){if(this.searchResults&&this.activeLink&&this.navigatedByKeyboard){var e=this.activeLink.getClientRects()[0],t=this.searchResults.getClientRects()[0].top;e.bottom>window.innerHeight?this.searchResults.scrollTop+=e.bottom-window.innerHeight+80:e.top<t&&(this.searchResults.scrollTop-=t-e.top+80)}this.focusPlease&&this.input&&this.input.focus(),this.navigatedByKeyboard=!1,this.focusPlease=!1},e.prototype.componentDidMount=function(){this.props.showHideTrigger(this.toggleVisibility.bind(this))},e.prototype.render=function(e,t){var r=this;if(t.failedLoading){var n="file:"==window.location.protocol;return a("div",{id:"search",class:t.isVisible?"":"hidden"},a("div",{id:"search-results"},a("p",{class:"error"},"Failed to load file 'doc-index.json' containing definitions in this package."),n?a("p",{class:"error"},"To use quick jump, load this page with HTTP (from a local static file web server) instead of using the ",a("code",null,"file://")," protocol. (For security reasons, it is not possible to fetch auxiliary files using JS in a HTML page opened with ",a("code",null,"file://"),".)"):[]))}this.linkIndex=0;var o=function(e){e.stopPropagation()},i=d(10,t.moduleResults).map(function(e){return r.renderResultsInModule(e)});return a("div",{id:"search",class:t.isVisible?"":"hidden"},a("div",{id:"search-form",onMouseDown:o},a("input",{placeholder:"Search in package by name",ref:function(e){r.input=e},onFocus:this.show.bind(this),onClick:this.show.bind(this),onInput:this.updateResults.bind(this)})),a("div",{id:"search-results",ref:function(e){r.searchResults=e},onMouseDown:o,onMouseOver:function(e){for(var t=e.target;t&&"function"==typeof t.getAttribute;){var n=t.getAttribute("data-link-index");if("string"==typeof n){var o=parseInt(n,10);r.setState({activeLinkIndex:o});break}t=t.parentNode}}},""===t.searchString?[a(v,null),a(f,null)]:0==i.length?a(g,{searchString:t.searchString}):a("ul",null,i)))},e.prototype.renderResultsInModule=function(e){var n=this,t=e.items,o=e.module,r=this.state.expanded[o]||t.length<=10,i=r?t:d(8,t);return a("li",{class:"search-module"},a("h4",null,o),a("ul",null,i.map(function(e){return t=e.item,a("li",{class:"search-result"},n.navigationLink(n.props.baseUrl+"/"+t.link,{},a(p,{html:t.display_html})));var t}),r?[]:a("li",{class:"more-results"},this.actionLink(function(){var e=Object.assign({},n.state.expanded);e[o]=!0,n.setState({expanded:e})},{},"show "+(t.length-i.length)+" more results from this module"))))},e.prototype.navigationLink=function(e,t){for(var n=this,o=[],r=2;r<arguments.length;r++)o[r-2]=arguments[r];var i=Object.assign({href:e,onClick:this.hide.bind(this)},t);return this.menuLink.apply(this,[i,function(){window.location.href=e,n.hide()}].concat(o))},e.prototype.actionLink=function(t,e){for(var n=[],o=2;o<arguments.length;o++)n[o-2]=arguments[o];var r=Object.assign({href:"#",onClick:function(e){e.preventDefault(),t()}},e);return this.menuLink.apply(this,[r,t].concat(n))},e.prototype.menuLink=function(e,t){for(var n=this,o=[],r=2;r<arguments.length;r++)o[r-2]=arguments[r];var i=this.linkIndex;i===this.state.activeLinkIndex&&(e.class=(e.class?e.class+" ":"")+"active-link",e.ref=function(e){e&&(n.activeLink=e)},this.activeLinkAction=t);var s=Object.assign({"data-link-index":i},e);return this.linkIndex+=1,a.apply(void 0,["a",s].concat(o))},e}(l),p=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return r(t,e),t.prototype.shouldComponentUpdate=function(e){return this.props.html!==e.html},t.prototype.render=function(e){return a("div",{dangerouslySetInnerHTML:{__html:e.html}})},t}(l);function f(){return a("table",{class:"keyboard-shortcuts"},a("tr",null,a("th",null,"Key"),a("th",null,"Shortcut")),a("tr",null,a("td",null,a("span",{class:"key"},"s")),a("td",null,"Open this search box")),a("tr",null,a("td",null,a("span",{class:"key"},"esc")),a("td",null,"Close this search box")),a("tr",null,a("td",null,a("span",{class:"key"},"↓"),",",a("span",{class:"key"},"ctrl")," + ",a("span",{class:"key"},"j")),a("td",null,"Move down in search results")),a("tr",null,a("td",null,a("span",{class:"key"},"↑"),",",a("span",{class:"key"},"ctrl")," + ",a("span",{class:"key"},"k")),a("td",null,"Move up in search results")),a("tr",null,a("td",null,a("span",{class:"key"},"↵")),a("td",null,"Go to active search result")))}function v(){return a("p",null,"You can find any exported type, constructor, class, function or pattern defined in this package by (approximate) name.")}function g(e){var t=[a("p",null,"Your search for '",e.searchString,"' produced the following list of results: ",a("code",null,"[]"),"."),a("p",null,a("code",null,"Nothing")," matches your query for '",e.searchString,"'."),a("p",null,a("code",null,"Left \"no matches for '",e.searchString,"'\" :: Either String (NonEmpty SearchResult)"))];return t[(e.searchString||"a").charCodeAt(0)%t.length]}function m(e,t){s.render(a(h,{baseUrl:e||".",showHideTrigger:t||u}),document.body)}n.init=m,window.quickNav={init:m}},{"fuse.js":6,preact:7}],5:[function(e,t,n){"use strict";var o,r=this&&this.__extends||(o=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},function(e,t){function n(){this.constructor=e}o(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)});Object.defineProperty(n,"__esModule",{value:!0});var i=e("./cookies"),s=e("preact"),a=s.h,l=s.Component;function c(){return Array.prototype.slice.call(document.getElementsByTagName("link")).filter(function(e){return-1!=e.rel.indexOf("style")&&e.title})}function u(e){for(var t=c(),n=null,o=0;o<t.length;o++){var r=t[o];r.disabled=!0,r.title==e&&(n=r)}n?(n.disabled=!1,i.setCookie("haddock-style",e)):(t[0].disabled=!1,i.clearCookie("haddock-style"))}var d=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return r(t,e),t.prototype.render=function(t){return a("li",null,a("a",{href:"#",onClick:function(e){e.preventDefault(),t.onClick()}},t.title))},t}(l);var h=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return r(t,e),t.prototype.componentWillMount=function(){var t=this;document.addEventListener("mousedown",this.hide.bind(this)),document.addEventListener("keydown",function(e){t.state.isVisible&&"Escape"===e.key&&t.hide()})},t.prototype.hide=function(){this.setState({isVisible:!1})},t.prototype.show=function(){this.state.isVisible||this.setState({isVisible:!0})},t.prototype.toggleVisibility=function(){this.state.isVisible?this.hide():this.show()},t.prototype.componentDidMount=function(){this.props.showHideTrigger(this.toggleVisibility.bind(this))},t.prototype.render=function(e,t){var n=this;return a("div",{id:"style",class:t.isVisible?"":"hidden"},a("div",{id:"style-menu",class:"dropdown-menu",onMouseDown:function(e){e.stopPropagation()}},e.styles.map(function(t){return a("button",{type:"button",onClick:function(e){n.hide(),u(t)}},t)})))},t}(l);n.init=function(e){var t,n=c().map(function(e){return e.title});(t=i.getCookie("haddock-style"))&&u(t),s.render(a(h,{showHideTrigger:e||function(e){return function(e,t){if(1<e.length){var n=document.querySelector("#page-menu"),o=document.createElement("li");n.appendChild(o),s.render(a(d,{onClick:t,title:"Styles"}),n,o)}}(n,e)},styles:n}),document.body)}},{"./cookies":1,preact:7}],6:[function(e,t,n){var o,r;o=this,r=function(){return function(n){var o={};function r(e){if(o[e])return o[e].exports;var t=o[e]={i:e,l:!1,exports:{}};return n[e].call(t.exports,t,t.exports,r),t.l=!0,t.exports}return r.m=n,r.c=o,r.i=function(e){return e},r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:n})},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=8)}([function(e,t,n){"use strict";e.exports=function(e){return Array.isArray?Array.isArray(e):"[object Array]"===Object.prototype.toString.call(e)}},function(e,t,n){"use strict";var o=function(){function o(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(e,t,n){return t&&o(e.prototype,t),n&&o(e,n),e}}();var u=n(5),d=n(7),_=n(4),r=function(){function y(e,t){var n=t.location,o=void 0===n?0:n,r=t.distance,i=void 0===r?100:r,s=t.threshold,a=void 0===s?.6:s,l=t.maxPatternLength,c=void 0===l?32:l,u=t.isCaseSensitive,d=void 0!==u&&u,h=t.tokenSeparator,p=void 0===h?/ +/g:h,f=t.findAllMatches,v=void 0!==f&&f,g=t.minMatchCharLength,m=void 0===g?1:g;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,y),this.options={location:o,distance:i,threshold:a,maxPatternLength:c,isCaseSensitive:d,tokenSeparator:p,findAllMatches:v,minMatchCharLength:m},this.pattern=this.options.isCaseSensitive?e:e.toLowerCase(),this.pattern.length<=c&&(this.patternAlphabet=_(this.pattern))}return o(y,[{key:"search",value:function(e){if(this.options.isCaseSensitive||(e=e.toLowerCase()),this.pattern===e)return{isMatch:!0,score:0,matchedIndices:[[0,e.length-1]]};var t=this.options,n=t.maxPatternLength,o=t.tokenSeparator;if(this.pattern.length>n)return u(e,this.pattern,o);var r=this.options,i=r.location,s=r.distance,a=r.threshold,l=r.findAllMatches,c=r.minMatchCharLength;return d(e,this.pattern,this.patternAlphabet,{location:i,distance:s,threshold:a,findAllMatches:l,minMatchCharLength:c})}}]),y}();e.exports=r},function(e,t,n){"use strict";var u=n(0);e.exports=function(e,t){return function e(t,n,o){if(n){var r=n.indexOf("."),i=n,s=null;-1!==r&&(i=n.slice(0,r),s=n.slice(r+1));var a=t[i];if(null!=a)if(s||"string"!=typeof a&&"number"!=typeof a)if(u(a))for(var l=0,c=a.length;l<c;l+=1)e(a[l],s,o);else s&&e(a,s,o);else o.push(a.toString())}else o.push(t);return o}(e,t,[])}},function(e,t,n){"use strict";e.exports=function(){for(var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:[],t=1<arguments.length&&void 0!==arguments[1]?arguments[1]:1,n=[],o=-1,r=-1,i=0,s=e.length;i<s;i+=1){var a=e[i];a&&-1===o?o=i:a||-1===o||(t<=(r=i-1)-o+1&&n.push([o,r]),o=-1)}return e[i-1]&&t<=i-o&&n.push([o,i-1]),n}},function(e,t,n){"use strict";e.exports=function(e){for(var t={},n=e.length,o=0;o<n;o+=1)t[e.charAt(o)]=0;for(var r=0;r<n;r+=1)t[e.charAt(r)]|=1<<n-r-1;return t}},function(e,t,n){"use strict";var u=/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g;e.exports=function(e,t){var n=2<arguments.length&&void 0!==arguments[2]?arguments[2]:/ +/g,o=new RegExp(t.replace(u,"\\$&").replace(n,"|")),r=e.match(o),i=!!r,s=[];if(i)for(var a=0,l=r.length;a<l;a+=1){var c=r[a];s.push([e.indexOf(c),c.length-1])}return{score:i?.5:1,isMatch:i,matchedIndices:s}}},function(e,t,n){"use strict";e.exports=function(e,t){var n=t.errors,o=void 0===n?0:n,r=t.currentLocation,i=void 0===r?0:r,s=t.expectedLocation,a=void 0===s?0:s,l=t.distance,c=void 0===l?100:l,u=o/e.length,d=Math.abs(a-i);return c?u+d/c:d?1:u}},function(e,t,n){"use strict";var V=n(6),D=n(3);e.exports=function(e,t,n,o){for(var r=o.location,i=void 0===r?0:r,s=o.distance,a=void 0===s?100:s,l=o.threshold,c=void 0===l?.6:l,u=o.findAllMatches,d=void 0!==u&&u,h=o.minMatchCharLength,p=void 0===h?1:h,f=i,v=e.length,g=c,m=e.indexOf(t,f),y=t.length,_=[],b=0;b<v;b+=1)_[b]=0;if(-1!==m){var k=V(t,{errors:0,currentLocation:m,expectedLocation:f,distance:a});if(g=Math.min(k,g),-1!==(m=e.lastIndexOf(t,f+y))){var S=V(t,{errors:0,currentLocation:m,expectedLocation:f,distance:a});g=Math.min(S,g)}}m=-1;for(var x=[],w=1,C=y+v,L=1<<y-1,M=0;M<y;M+=1){for(var I=0,E=C;I<E;){V(t,{errors:M,currentLocation:f+E,expectedLocation:f,distance:a})<=g?I=E:C=E,E=Math.floor((C-I)/2+I)}C=E;var O=Math.max(1,f-E+1),A=d?v:Math.min(f+E,v)+y,T=Array(A+2);T[A+1]=(1<<M)-1;for(var N=A;O<=N;N-=1){var P=N-1,j=n[e.charAt(P)];if(j&&(_[P]=1),T[N]=(T[N+1]<<1|1)&j,0!==M&&(T[N]|=(x[N+1]|x[N])<<1|1|x[N+1]),T[N]&L&&(w=V(t,{errors:M,currentLocation:P,expectedLocation:f,distance:a}))<=g){if(g=w,(m=P)<=f)break;O=Math.max(1,2*f-m)}}if(g<V(t,{errors:M+1,currentLocation:f,expectedLocation:f,distance:a}))break;x=T}return{isMatch:0<=m,score:0===w?.001:w,matchedIndices:D(_,p)}}},function(e,t,n){"use strict";var o=function(){function o(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(e,t,n){return t&&o(e.prototype,t),n&&o(e,n),e}}();var i=n(1),R=n(2),V=n(0),r=function(){function U(e,t){var n=t.location,o=void 0===n?0:n,r=t.distance,i=void 0===r?100:r,s=t.threshold,a=void 0===s?.6:s,l=t.maxPatternLength,c=void 0===l?32:l,u=t.caseSensitive,d=void 0!==u&&u,h=t.tokenSeparator,p=void 0===h?/ +/g:h,f=t.findAllMatches,v=void 0!==f&&f,g=t.minMatchCharLength,m=void 0===g?1:g,y=t.id,_=void 0===y?null:y,b=t.keys,k=void 0===b?[]:b,S=t.shouldSort,x=void 0===S||S,w=t.getFn,C=void 0===w?R:w,L=t.sortFn,M=void 0===L?function(e,t){return e.score-t.score}:L,I=t.tokenize,E=void 0!==I&&I,O=t.matchAllTokens,A=void 0!==O&&O,T=t.includeMatches,N=void 0!==T&&T,P=t.includeScore,j=void 0!==P&&P,V=t.verbose,D=void 0!==V&&V;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,U),this.options={location:o,distance:i,threshold:a,maxPatternLength:c,isCaseSensitive:d,tokenSeparator:p,findAllMatches:v,minMatchCharLength:m,id:_,keys:k,includeMatches:N,includeScore:j,shouldSort:x,getFn:C,sortFn:M,verbose:D,tokenize:E,matchAllTokens:A},this.setCollection(e)}return o(U,[{key:"setCollection",value:function(e){return this.list=e}},{key:"search",value:function(e){this._log('---------\nSearch pattern: "'+e+'"');var t=this._prepareSearchers(e),n=t.tokenSearchers,o=t.fullSearcher,r=this._search(n,o),i=r.weights,s=r.results;return this._computeScore(i,s),this.options.shouldSort&&this._sort(s),this._format(s)}},{key:"_prepareSearchers",value:function(){var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:"",t=[];if(this.options.tokenize)for(var n=e.split(this.options.tokenSeparator),o=0,r=n.length;o<r;o+=1)t.push(new i(n[o],this.options));return{tokenSearchers:t,fullSearcher:new i(e,this.options)}}},{key:"_search",value:function(){var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:[],t=arguments[1],n=this.list,o={},r=[];if("string"==typeof n[0]){for(var i=0,s=n.length;i<s;i+=1)this._analyze({key:"",value:n[i],record:i,index:i},{resultMap:o,results:r,tokenSearchers:e,fullSearcher:t});return{weights:null,results:r}}for(var a={},l=0,c=n.length;l<c;l+=1)for(var u=n[l],d=0,h=this.options.keys.length;d<h;d+=1){var p=this.options.keys[d];if("string"!=typeof p){if(a[p.name]={weight:1-p.weight||1},p.weight<=0||1<p.weight)throw new Error("Key weight has to be > 0 and <= 1");p=p.name}else a[p]={weight:1};this._analyze({key:p,value:this.options.getFn(u,p),record:u,index:l},{resultMap:o,results:r,tokenSearchers:e,fullSearcher:t})}return{weights:a,results:r}}},{key:"_analyze",value:function(e,t){var n=e.key,o=e.arrayIndex,r=void 0===o?-1:o,i=e.value,s=e.record,a=e.index,l=t.tokenSearchers,c=void 0===l?[]:l,u=t.fullSearcher,d=void 0===u?[]:u,h=t.resultMap,p=void 0===h?{}:h,f=t.results,v=void 0===f?[]:f;if(null!=i){var g=!1,m=-1,y=0;if("string"==typeof i){this._log("\nKey: "+(""===n?"-":n));var _=d.search(i);if(this._log('Full text: "'+i+'", score: '+_.score),this.options.tokenize){for(var b=i.split(this.options.tokenSeparator),k=[],S=0;S<c.length;S+=1){var x=c[S];this._log('\nPattern: "'+x.pattern+'"');for(var w=!1,C=0;C<b.length;C+=1){var L=b[C],M=x.search(L),I={};M.isMatch?(I[L]=M.score,w=g=!0,k.push(M.score)):(I[L]=1,this.options.matchAllTokens||k.push(1)),this._log('Token: "'+L+'", score: '+I[L])}w&&(y+=1)}m=k[0];for(var E=k.length,O=1;O<E;O+=1)m+=k[O];m/=E,this._log("Token score average:",m)}var A=_.score;-1<m&&(A=(A+m)/2),this._log("Score average:",A);var T=!this.options.tokenize||!this.options.matchAllTokens||y>=c.length;if(this._log("\nCheck Matches: "+T),(g||_.isMatch)&&T){var N=p[a];N?N.output.push({key:n,arrayIndex:r,value:i,score:A,matchedIndices:_.matchedIndices}):(p[a]={item:s,output:[{key:n,arrayIndex:r,value:i,score:A,matchedIndices:_.matchedIndices}]},v.push(p[a]))}}else if(V(i))for(var P=0,j=i.length;P<j;P+=1)this._analyze({key:n,arrayIndex:P,value:i[P],record:s,index:a},{resultMap:p,results:v,tokenSearchers:c,fullSearcher:d})}}},{key:"_computeScore",value:function(e,t){this._log("\n\nComputing score:\n");for(var n=0,o=t.length;n<o;n+=1){for(var r=t[n].output,i=r.length,s=1,a=1,l=0;l<i;l+=1){var c=e?e[r[l].key].weight:1,u=(1===c?r[l].score:r[l].score||.001)*c;1!==c?a=Math.min(a,u):s*=r[l].nScore=u}t[n].score=1===a?s:a,this._log(t[n])}}},{key:"_sort",value:function(e){this._log("\n\nSorting...."),e.sort(this.options.sortFn)}},{key:"_format",value:function(e){var t=[];this.options.verbose&&this._log("\n\nOutput:\n\n",JSON.stringify(e));var n=[];this.options.includeMatches&&n.push(function(e,t){var n=e.output;t.matches=[];for(var o=0,r=n.length;o<r;o+=1){var i=n[o];if(0!==i.matchedIndices.length){var s={indices:i.matchedIndices,value:i.value};i.key&&(s.key=i.key),i.hasOwnProperty("arrayIndex")&&-1<i.arrayIndex&&(s.arrayIndex=i.arrayIndex),t.matches.push(s)}}}),this.options.includeScore&&n.push(function(e,t){t.score=e.score});for(var o=0,r=e.length;o<r;o+=1){var i=e[o];if(this.options.id&&(i.item=this.options.getFn(i.item,this.options.id)[0]),n.length){for(var s={item:i.item},a=0,l=n.length;a<l;a+=1)n[a](i,s);t.push(s)}else t.push(i.item)}return t}},{key:"_log",value:function(){var e;this.options.verbose&&(e=console).log.apply(e,arguments)}}]),U}();e.exports=r}])},"object"==typeof n&&"object"==typeof t?t.exports=r():"function"==typeof define&&define.amd?define("Fuse",[],r):"object"==typeof n?n.Fuse=r():o.Fuse=r()},{}],7:[function(e,y,t){!function(){"use strict";function n(e,t){var n,o,r,i,s=d;for(i=arguments.length;2<i--;)u.push(arguments[i]);for(t&&null!=t.children&&(u.length||u.push(t.children),delete t.children);u.length;)if((o=u.pop())&&void 0!==o.pop)for(i=o.length;i--;)u.push(o[i]);else"boolean"==typeof o&&(o=null),(r="function"!=typeof e)&&(null==o?o="":"number"==typeof o?o=String(o):"string"!=typeof o&&(r=!1)),r&&n?s[s.length-1]+=o:s===d?s=[o]:s.push(o),n=r;var a=new c;return a.nodeName=e,a.children=s,a.attributes=null==t?void 0:t,a.key=null==t?void 0:t.key,void 0!==D.vnode&&D.vnode(a),a}function L(e,t){for(var n in t)e[n]=t[n];return e}function i(e){!e.__d&&(e.__d=!0)&&1==p.push(e)&&(D.debounceRendering||r)(t)}function t(){var e,t=p;for(p=[];e=t.pop();)e.__d&&j(e)}function C(e,t){return e.__n===t||e.nodeName.toLowerCase()===t.toLowerCase()}function M(e){var t=L({},e.attributes);t.children=e.children;var n=e.nodeName.defaultProps;if(void 0!==n)for(var o in n)void 0===t[o]&&(t[o]=n[o]);return t}function I(e){var t=e.parentNode;t&&t.removeChild(e)}function v(e,t,n,o,r){if("className"===t&&(t="class"),"key"===t);else if("ref"===t)n&&n(null),o&&o(e);else if("class"!==t||r)if("style"===t){if(o&&"string"!=typeof o&&"string"!=typeof n||(e.style.cssText=o||""),o&&"object"==typeof o){if("string"!=typeof n)for(var i in n)i in o||(e.style[i]="");for(var i in o)e.style[i]="number"==typeof o[i]&&!1===h.test(i)?o[i]+"px":o[i]}}else if("dangerouslySetInnerHTML"===t)o&&(e.innerHTML=o.__html||"");else if("o"==t[0]&&"n"==t[1]){var s=t!==(t=t.replace(/Capture$/,""));t=t.toLowerCase().substring(2),o?n||e.addEventListener(t,l,s):e.removeEventListener(t,l,s),(e.__l||(e.__l={}))[t]=o}else if("list"!==t&&"type"!==t&&!r&&t in e){try{e[t]=null==o?"":o}catch(e){}null!=o&&!1!==o||"spellcheck"==t||e.removeAttribute(t)}else{var a=r&&t!==(t=t.replace(/^xlink:?/,""));null==o||!1===o?a?e.removeAttributeNS("http://www.w3.org/1999/xlink",t.toLowerCase()):e.removeAttribute(t):"function"!=typeof o&&(a?e.setAttributeNS("http://www.w3.org/1999/xlink",t.toLowerCase(),o):e.setAttribute(t,o))}else e.className=o||""}function l(e){return this.__l[e.type](D.event&&D.event(e)||e)}function E(){for(var e;e=U.pop();)D.afterMount&&D.afterMount(e),e.componentDidMount&&e.componentDidMount()}function O(e,t,n,o,r,i){R++||(g=null!=r&&void 0!==r.ownerSVGElement,m=null!=e&&!("__preactattr_"in e));var s=A(e,t,n,o,i);return r&&s.parentNode!==r&&r.appendChild(s),--R||(m=!1,i||E()),s}function A(e,t,n,o,r){var i=e,s=g;if(null!=t&&"boolean"!=typeof t||(t=""),"string"==typeof t||"number"==typeof t)return e&&void 0!==e.splitText&&e.parentNode&&(!e._component||r)?e.nodeValue!=t&&(e.nodeValue=t):(i=document.createTextNode(t),e&&(e.parentNode&&e.parentNode.replaceChild(i,e),T(e,!0))),i.__preactattr_=!0,i;var a,l,c=t.nodeName;if("function"==typeof c)return function(e,t,n,o){var r=e&&e._component,i=r,s=e,a=r&&e._componentConstructor===t.nodeName,l=a,c=M(t);for(;r&&!l&&(r=r.__u);)l=r.constructor===t.nodeName;r&&l&&(!o||r._component)?(P(r,c,3,n,o),e=r.base):(i&&!a&&(V(i),e=s=null),r=N(t.nodeName,c,n),e&&!r.__b&&(r.__b=e,s=null),P(r,c,1,n,o),e=r.base,s&&e!==s&&(s._component=null,T(s,!1)));return e}(e,t,n,o);if(g="svg"===c||"foreignObject"!==c&&g,c=String(c),(!e||!C(e,c))&&(a=c,(l=g?document.createElementNS("http://www.w3.org/2000/svg",a):document.createElement(a)).__n=a,i=l,e)){for(;e.firstChild;)i.appendChild(e.firstChild);e.parentNode&&e.parentNode.replaceChild(i,e),T(e,!0)}var u=i.firstChild,d=i.__preactattr_,h=t.children;if(null==d){d=i.__preactattr_={};for(var p=i.attributes,f=p.length;f--;)d[p[f].name]=p[f].value}return!m&&h&&1===h.length&&"string"==typeof h[0]&&null!=u&&void 0!==u.splitText&&null==u.nextSibling?u.nodeValue!=h[0]&&(u.nodeValue=h[0]):(h&&h.length||null!=u)&&function(e,t,n,o,r){var i,s,a,l,c,u=e.childNodes,d=[],h={},p=0,f=0,v=u.length,g=0,m=t?t.length:0;if(0!==v)for(var y=0;y<v;y++){var _=u[y],b=_.__preactattr_,k=m&&b?_._component?_._component.__k:b.key:null;null!=k?(p++,h[k]=_):(b||(void 0!==_.splitText?!r||_.nodeValue.trim():r))&&(d[g++]=_)}if(0!==m)for(var y=0;y<m;y++){l=t[y],c=null;var k=l.key;if(null!=k)p&&void 0!==h[k]&&(c=h[k],h[k]=void 0,p--);else if(f<g)for(i=f;i<g;i++)if(void 0!==d[i]&&(S=s=d[i],w=r,"string"==typeof(x=l)||"number"==typeof x?void 0!==S.splitText:"string"==typeof x.nodeName?!S._componentConstructor&&C(S,x.nodeName):w||S._componentConstructor===x.nodeName)){c=s,d[i]=void 0,i===g-1&&g--,i===f&&f++;break}c=A(c,l,n,o),a=u[y],c&&c!==e&&c!==a&&(null==a?e.appendChild(c):c===a.nextSibling?I(a):e.insertBefore(c,a))}var S,x,w;if(p)for(var y in h)void 0!==h[y]&&T(h[y],!1);for(;f<=g;)void 0!==(c=d[g--])&&T(c,!1)}(i,h,n,o,m||null!=d.dangerouslySetInnerHTML),function(e,t,n){var o;for(o in n)t&&null!=t[o]||null==n[o]||v(e,o,n[o],n[o]=void 0,g);for(o in t)"children"===o||"innerHTML"===o||o in n&&t[o]===("value"===o||"checked"===o?e[o]:n[o])||v(e,o,n[o],n[o]=t[o],g)}(i,t.attributes,d),g=s,i}function T(e,t){var n=e._component;n?V(n):(null!=e.__preactattr_&&e.__preactattr_.ref&&e.__preactattr_.ref(null),!1!==t&&null!=e.__preactattr_||I(e),o(e))}function o(e){for(e=e.lastChild;e;){var t=e.previousSibling;T(e,!0),e=t}}function N(e,t,n){var o,r=f.length;for(e.prototype&&e.prototype.render?(o=new e(t,n),a.call(o,t,n)):((o=new a(t,n)).constructor=e,o.render=s);r--;)if(f[r].constructor===e)return o.__b=f[r].__b,f.splice(r,1),o;return o}function s(e,t,n){return this.constructor(e,n)}function P(e,t,n,o,r){e.__x||(e.__x=!0,e.__r=t.ref,e.__k=t.key,delete t.ref,delete t.key,void 0===e.constructor.getDerivedStateFromProps&&(!e.base||r?e.componentWillMount&&e.componentWillMount():e.componentWillReceiveProps&&e.componentWillReceiveProps(t,o)),o&&o!==e.context&&(e.__c||(e.__c=e.context),e.context=o),e.__p||(e.__p=e.props),e.props=t,e.__x=!1,0!==n&&(1!==n&&!1===D.syncComponentUpdates&&e.base?i(e):j(e,1,r)),e.__r&&e.__r(e))}function j(e,t,n,o){if(!e.__x){var r,i,s,a=e.props,l=e.state,c=e.context,u=e.__p||a,d=e.__s||l,h=e.__c||c,p=e.base,f=e.__b,v=p||f,g=e._component,m=!1,y=h;if(e.constructor.getDerivedStateFromProps&&(l=L(L({},l),e.constructor.getDerivedStateFromProps(a,l)),e.state=l),p&&(e.props=u,e.state=d,e.context=h,2!==t&&e.shouldComponentUpdate&&!1===e.shouldComponentUpdate(a,l,c)?m=!0:e.componentWillUpdate&&e.componentWillUpdate(a,l,c),e.props=a,e.state=l,e.context=c),e.__p=e.__s=e.__c=e.__b=null,e.__d=!1,!m){r=e.render(a,l,c),e.getChildContext&&(c=L(L({},c),e.getChildContext())),p&&e.getSnapshotBeforeUpdate&&(y=e.getSnapshotBeforeUpdate(u,d));var _,b,k=r&&r.nodeName;if("function"==typeof k){var S=M(r);(i=g)&&i.constructor===k&&S.key==i.__k?P(i,S,1,c,!1):(_=i,e._component=i=N(k,S,c),i.__b=i.__b||f,i.__u=e,P(i,S,0,c,!1),j(i,1,n,!0)),b=i.base}else s=v,(_=g)&&(s=e._component=null),(v||1===t)&&(s&&(s._component=null),b=O(s,r,c,n||!p,v&&v.parentNode,!0));if(v&&b!==v&&i!==g){var x=v.parentNode;x&&b!==x&&(x.replaceChild(b,v),_||(v._component=null,T(v,!1)))}if(_&&V(_),(e.base=b)&&!o){for(var w=e,C=e;C=C.__u;)(w=C).base=b;b._component=w,b._componentConstructor=w.constructor}}for(!p||n?U.unshift(e):m||(e.componentDidUpdate&&e.componentDidUpdate(u,d,y),D.afterUpdate&&D.afterUpdate(e));e.__h.length;)e.__h.pop().call(e);R||o||E()}}function V(e){D.beforeUnmount&&D.beforeUnmount(e);var t=e.base;e.__x=!0,e.componentWillUnmount&&e.componentWillUnmount(),e.base=null;var n=e._component;n?V(n):t&&(t.__preactattr_&&t.__preactattr_.ref&&t.__preactattr_.ref(null),I(e.__b=t),f.push(e),o(t)),e.__r&&e.__r(null)}function a(e,t){this.__d=!0,this.context=t,this.props=e,this.state=this.state||{},this.__h=[]}var c=function(){},D={},u=[],d=[],r="function"==typeof Promise?Promise.resolve().then.bind(Promise.resolve()):setTimeout,h=/acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i,p=[],U=[],R=0,g=!1,m=!1,f=[];L(a.prototype,{setState:function(e,t){this.__s||(this.__s=this.state),this.state=L(L({},this.state),"function"==typeof e?e(this.state,this.props):e),t&&this.__h.push(t),i(this)},forceUpdate:function(e){e&&this.__h.push(e),j(this,2)},render:function(){}});var e={h:n,createElement:n,cloneElement:function(e,t){return n(e.nodeName,L(L({},e.attributes),t),2<arguments.length?[].slice.call(arguments,2):e.children)},Component:a,render:function(e,t,n){return O(n,e,{},!1,t,!1)},rerender:t,options:D};void 0!==y?y.exports=e:self.preact=e}()},{}]},{},[3]);
+!function i(s,a,l){function c(t,e){if(!a[t]){if(!s[t]){var n="function"==typeof require&&require;if(!e&&n)return n(t,!0);if(u)return u(t,!0);var o=new Error("Cannot find module '"+t+"'");throw o.code="MODULE_NOT_FOUND",o}var r=a[t]={exports:{}};s[t][0].call(r.exports,function(e){return c(s[t][1][e]||e)},r,r.exports,i,s,a,l)}return a[t].exports}for(var u="function"==typeof require&&require,e=0;e<l.length;e++)c(l[e]);return c}({1:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.setCookie=function(e,t){document.cookie=e+"="+encodeURIComponent(t)+";path=/;"},n.clearCookie=function(e){document.cookie=e+"=;path=/;expires=Thu, 01-Jan-1970 00:00:01 GMT;"},n.getCookie=function(e){for(var t=e+"=",n=document.cookie.split(";"),o=0;o<n.length;o++){for(var r=n[o];" "==r.charAt(0);)r=r.substring(1,r.length);if(0==r.indexOf(t))return decodeURIComponent(r.substring(t.length,r.length))}return null}},{}],2:[function(e,t,n){"use strict";var o,r=this&&this.__extends||(o=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},function(e,t){function n(){this.constructor=e}o(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)});Object.defineProperty(n,"__esModule",{value:!0});var i,s,a=e("preact"),l=a.h,c=a.Component;(s=i||(i={}))[s.Closed=0]="Closed",s[s.Open=1]="Open";var u={defaultInstanceState:i.Open,rememberToggles:!0},d=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return r(t,e),t.prototype.render=function(t){return l("li",null,l("a",{href:"#",onClick:function(e){e.preventDefault(),t.onClick()}},t.title))},t}(c);function h(e){var t=document.querySelector("#page-menu"),n=document.createElement("li");t.insertBefore(n,t.firstChild),a.render(l(d,{onClick:e,title:"Instances"}),t,n)}var p=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return r(t,e),t.prototype.componentWillMount=function(){var t=this;document.addEventListener("mousedown",this.hide.bind(this)),document.addEventListener("keydown",function(e){t.state.isVisible&&"Escape"===e.key&&t.hide()})},t.prototype.hide=function(){this.setState({isVisible:!1})},t.prototype.show=function(){this.state.isVisible||this.setState({isVisible:!0})},t.prototype.toggleVisibility=function(){this.state.isVisible?this.hide():this.show()},t.prototype.componentDidMount=function(){this.props.showHideTrigger(this.toggleVisibility.bind(this))},t.prototype.render=function(e,t){return l("div",{id:"preferences",class:t.isVisible?"":"hidden"},l("div",{id:"preferences-menu",class:"dropdown-menu",onMouseDown:function(e){e.stopPropagation()}},l(b,null)))},t}(c);function f(){var e=JSON.stringify(u);try{localStorage.setItem("global",e)}catch(e){}}var v=!1;function g(){if(!v){v=!0;var e=localStorage.getItem("global");if(e)try{var t=JSON.parse(e);u.defaultInstanceState=t.defaultInstanceState,u.rememberToggles=t.rememberToggles}catch(e){if(!(e instanceof SyntaxError||e instanceof TypeError))throw e;localStorage.removeItem("global")}}}function m(t){return function(e){u.defaultInstanceState=t,A(),f(),E(),O()}}function y(e){var t=e.target.checked;u.rememberToggles=t,f(),E(),O()}function _(e){var t=document.getElementById("default-collapse-instances");null!==t&&(t.checked?m(i.Closed)(e):m(i.Open)(e))}function b(){return g(),l("div",null,l("div",null,l("button",{type:"button",onClick:j},"Expand All Instances"),l("button",{type:"button",onClick:P},"Collapse All Instances")),l("div",null,l("input",{type:"checkbox",id:"default-collapse-instances",name:"default-instance-state",checked:u.defaultInstanceState===i.Closed,onClick:_}),l("span",null,"Collapse All Instances By Default")),l("div",null,l("input",{type:"checkbox",id:"remember-toggles",name:"remember-toggles",checked:u.rememberToggles,onClick:y}),l("label",{for:"remember-toggles"},"Remember Manually Collapsed/Expanded Instances")))}var k={};function S(e){var t=k[e];if(null==t)throw new Error("could not find <details> element with id '"+e+"'");return t}function x(){return u.defaultInstanceState==i.Open}function w(e){for(var t=S(e.target.id),n=t.element.open,o=0,r=t.toggles;o<r.length;o++){var i=r[o];i.classList.contains("details-toggle-control")&&(i.classList.add(n?"collapser":"expander"),i.classList.remove(n?"expander":"collapser"))}}function C(e){var t=e.getAttribute("data-details-id");if(!t)throw new Error("element with class "+e+" has no 'data-details-id' attribute!");return t}function L(e){var t=S(C(e)).element;t.open=!t.open}var M="local-details-config:";function I(){return M+document.location.pathname}function E(){for(var e=[],t=0;t<localStorage.length;++t){var n=localStorage.key(t);null!==n&&n.startsWith(M)&&e.push(n)}e.forEach(function(e){localStorage.removeItem(e)})}function O(){if(u.rememberToggles){var e=Array.prototype.slice.call(document.getElementsByClassName("instances details-toggle details-toggle-control")),n=[];e.forEach(function(e){var t=C(e);document.getElementById(t).open!=x()&&n.push(t)});var t=JSON.stringify(n);try{localStorage.setItem(I(),t)}catch(e){}}}function A(){switch(u.defaultInstanceState){case i.Closed:N(!0);break;case i.Open:N(!1)}}function T(e){L(e.currentTarget),O()}function N(o){var e=document.getElementsByClassName("subs instances");[].forEach.call(e,function(e){var t=o?"collapser":"expander",n=e.getElementsByClassName("instances "+t)[0];n&&L(n)})}function P(){N(!0),O()}function j(){N(!1),O()}n.init=function(e){!function(){for(var e=0,t=Array.prototype.slice.call(document.getElementsByTagName("details"));e<t.length;e++){var n=t[e];"string"==typeof n.id&&0<n.id.length&&(k[n.id]={element:n,toggles:[]},n.addEventListener("toggle",w))}}(),Array.prototype.slice.call(document.getElementsByClassName("details-toggle")).forEach(function(e){var t=S(C(e));t.toggles.push(e),e.addEventListener("click",T),e.classList.contains("details-toggle-control")&&e.classList.add(t.element.open?"collapser":"expander")}),function(){if(g(),A(),u.rememberToggles){var e=localStorage.getItem(I());if(e)try{JSON.parse(e).forEach(function(e){S(e).element.open=!x()})}catch(e){if(!(e instanceof SyntaxError||e instanceof TypeError))throw e;localStorage.removeItem(I())}}}(),a.render(l(p,{showHideTrigger:e||h}),document.body)}},{preact:7}],3:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var o,r=e("./style-menu"),i=e("./details-helper"),s=e("./quick-jump");o=function(){document.body.classList.add("js-enabled"),r.init(),i.init();var e=document.getElementById("head"),t=".";null!==e&&(t=e.getAttribute("data-base-url")||"."),s.init(t)},"interactive"===document.readyState?o():document.addEventListener("readystatechange",function(){"interactive"===document.readyState&&o()})},{"./details-helper":2,"./quick-jump":4,"./style-menu":5}],4:[function(e,t,n){"use strict";var o,r=this&&this.__extends||(o=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},function(e,t){function n(){this.constructor=e}o(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)});Object.defineProperty(n,"__esModule",{value:!0});var i=e("fuse.js"),s=e("preact"),a=s.h,l=s.Component;var c=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return r(t,e),t.prototype.render=function(t){return a("li",null,a("a",{href:"#",onClick:function(e){e.preventDefault(),t.onClick()}},t.title))},t}(l);function u(e,t){return t.length<=e?t:t.slice(0,e)}var d=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.linkIndex=0,e.focusPlease=!1,e.navigatedByKeyboard=!1,e}return r(e,t),e.prototype.componentWillMount=function(){var e,t,n,o,r=this;this.setState({searchString:"",isVisible:!1,expanded:{},activeLinkIndex:-1,moduleResults:[]}),e=this.props.baseUrl+"/doc-index.json",t=function(e){r.setState({fuse:new i(e,{threshold:.25,caseSensitive:!0,includeScore:!0,tokenize:!0,keys:[{name:"name",weight:.7},{name:"module",weight:.3}]}),moduleResults:[]})},n=function(e){console&&console.error("could not load 'doc-index.json' for searching",e),r.setState({failedLoading:!0})},(o=new XMLHttpRequest).onreadystatechange=function(){if(o.readyState===XMLHttpRequest.DONE)if(200===o.status){if(t)try{t(JSON.parse(o.responseText))}catch(e){n(o)}}else n&&n(o)},o.open("GET",e,!0),o.send(),document.addEventListener("mousedown",this.hide.bind(this)),document.addEventListener("keydown",function(e){r.state.isVisible&&("Escape"===e.key?r.hide():"ArrowUp"===e.key||"k"===e.key&&e.ctrlKey?(e.preventDefault(),r.navigateLinks(-1)):"ArrowDown"===e.key||"j"===e.key&&e.ctrlKey?(e.preventDefault(),r.navigateLinks(1)):"Enter"===e.key&&0<=r.state.activeLinkIndex&&r.followActiveLink()),"s"===e.key&&"input"!==e.target.tagName.toLowerCase()&&(e.preventDefault(),r.show())})},e.prototype.hide=function(){this.setState({isVisible:!1,searchString:""})},e.prototype.show=function(){this.state.isVisible||(this.focusPlease=!0,this.setState({isVisible:!0,activeLinkIndex:-1}))},e.prototype.toggleVisibility=function(){this.state.isVisible?this.hide():this.show()},e.prototype.navigateLinks=function(e){var t=Math.max(-1,Math.min(this.linkIndex-1,this.state.activeLinkIndex+e));this.navigatedByKeyboard=!0,this.setState({activeLinkIndex:t})},e.prototype.followActiveLink=function(){this.activeLinkAction&&this.activeLinkAction()},e.prototype.updateResults=function(){var e=this.input&&this.input.value||"",t=this.state.fuse.search(e),o={};t.forEach(function(e){var t=e.item.module;(o[t]||(o[t]=[])).push(e)});var r=[],n=function(e){var t=o[e],n=0;t.forEach(function(e){n+=1/e.score}),r.push({module:e,totalScore:1/n,items:t})};for(var i in o)n(i);r.sort(function(e,t){return e.totalScore-t.totalScore}),this.setState({searchString:e,isVisible:!0,moduleResults:r})},e.prototype.componentDidUpdate=function(){if(this.searchResults&&this.activeLink&&this.navigatedByKeyboard){var e=this.activeLink.getClientRects()[0],t=this.searchResults.getClientRects()[0].top;e.bottom>window.innerHeight?this.searchResults.scrollTop+=e.bottom-window.innerHeight+80:e.top<t&&(this.searchResults.scrollTop-=t-e.top+80)}this.focusPlease&&this.input&&this.input.focus(),this.navigatedByKeyboard=!1,this.focusPlease=!1},e.prototype.componentDidMount=function(){this.props.showHideTrigger(this.toggleVisibility.bind(this))},e.prototype.render=function(e,t){var r=this;if(t.failedLoading){var n="file:"==window.location.protocol;return a("div",{id:"search",class:t.isVisible?"":"hidden"},a("div",{id:"search-results"},a("p",{class:"error"},"Failed to load file 'doc-index.json' containing definitions in this package."),n?a("p",{class:"error"},"To use quick jump, load this page with HTTP (from a local static file web server) instead of using the ",a("code",null,"file://")," protocol. (For security reasons, it is not possible to fetch auxiliary files using JS in a HTML page opened with ",a("code",null,"file://"),".)"):[]))}this.linkIndex=0;var o=function(e){e.stopPropagation()},i=u(10,t.moduleResults).map(function(e){return r.renderResultsInModule(e)});return a("div",{id:"search",class:t.isVisible?"":"hidden"},a("div",{id:"search-form",onMouseDown:o},a("input",{placeholder:"Search in package by name",ref:function(e){r.input=e},onFocus:this.show.bind(this),onClick:this.show.bind(this),onInput:this.updateResults.bind(this)})),a("div",{id:"search-results",ref:function(e){r.searchResults=e},onMouseDown:o,onMouseOver:function(e){for(var t=e.target;t&&"function"==typeof t.getAttribute;){var n=t.getAttribute("data-link-index");if("string"==typeof n){var o=parseInt(n,10);r.setState({activeLinkIndex:o});break}t=t.parentNode}}},""===t.searchString?[a(f,null),a(p,null)]:0==i.length?a(v,{searchString:t.searchString}):a("ul",null,i)))},e.prototype.renderResultsInModule=function(e){var n=this,t=e.items,o=e.module,r=this.state.expanded[o]||t.length<=10,i=r?t:u(8,t);return a("li",{class:"search-module"},a("h4",null,o),a("ul",null,i.map(function(e){return t=e.item,a("li",{class:"search-result"},n.navigationLink(n.props.baseUrl+"/"+t.link,{},a(h,{html:t.display_html})));var t}),r?[]:a("li",{class:"more-results"},this.actionLink(function(){var e=Object.assign({},n.state.expanded);e[o]=!0,n.setState({expanded:e})},{},"show "+(t.length-i.length)+" more results from this module"))))},e.prototype.navigationLink=function(e,t){for(var n=this,o=[],r=2;r<arguments.length;r++)o[r-2]=arguments[r];var i=Object.assign({href:e,onClick:this.hide.bind(this)},t);return this.menuLink.apply(this,[i,function(){window.location.href=e,n.hide()}].concat(o))},e.prototype.actionLink=function(t,e){for(var n=[],o=2;o<arguments.length;o++)n[o-2]=arguments[o];var r=Object.assign({href:"#",onClick:function(e){e.preventDefault(),t()}},e);return this.menuLink.apply(this,[r,t].concat(n))},e.prototype.menuLink=function(e,t){for(var n=this,o=[],r=2;r<arguments.length;r++)o[r-2]=arguments[r];var i=this.linkIndex;i===this.state.activeLinkIndex&&(e.class=(e.class?e.class+" ":"")+"active-link",e.ref=function(e){e&&(n.activeLink=e)},this.activeLinkAction=t);var s=Object.assign({"data-link-index":i},e);return this.linkIndex+=1,a.apply(void 0,["a",s].concat(o))},e}(l),h=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return r(t,e),t.prototype.shouldComponentUpdate=function(e){return this.props.html!==e.html},t.prototype.render=function(e){return a("div",{dangerouslySetInnerHTML:{__html:e.html}})},t}(l);function p(){return a("table",{class:"keyboard-shortcuts"},a("tr",null,a("th",null,"Key"),a("th",null,"Shortcut")),a("tr",null,a("td",null,a("span",{class:"key"},"s")),a("td",null,"Open this search box")),a("tr",null,a("td",null,a("span",{class:"key"},"esc")),a("td",null,"Close this search box")),a("tr",null,a("td",null,a("span",{class:"key"},"↓"),",",a("span",{class:"key"},"ctrl")," + ",a("span",{class:"key"},"j")),a("td",null,"Move down in search results")),a("tr",null,a("td",null,a("span",{class:"key"},"↑"),",",a("span",{class:"key"},"ctrl")," + ",a("span",{class:"key"},"k")),a("td",null,"Move up in search results")),a("tr",null,a("td",null,a("span",{class:"key"},"↵")),a("td",null,"Go to active search result")))}function f(){return a("p",null,"You can find any exported type, constructor, class, function or pattern defined in this package by (approximate) name.")}function v(e){var t=[a("p",null,"Your search for '",e.searchString,"' produced the following list of results: ",a("code",null,"[]"),"."),a("p",null,a("code",null,"Nothing")," matches your query for '",e.searchString,"'."),a("p",null,a("code",null,"Left \"no matches for '",e.searchString,"'\" :: Either String (NonEmpty SearchResult)"))];return t[(e.searchString||"a").charCodeAt(0)%t.length]}function g(e,t){var n,o=document.getElementById("quick-jump-button");o&&s.render(a(d,{baseUrl:e||".",showHideTrigger:t||(n=o,function(e){var t=document.querySelector("#page-menu");s.render(a(c,{onClick:e,title:"Quick Jump"}),t,n)})}),document.body)}n.init=g,window.quickNav={init:g}},{"fuse.js":6,preact:7}],5:[function(e,t,n){"use strict";var o,r=this&&this.__extends||(o=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},function(e,t){function n(){this.constructor=e}o(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)});Object.defineProperty(n,"__esModule",{value:!0});var i=e("./cookies"),s=e("preact"),a=s.h,l=s.Component;function c(){return Array.prototype.slice.call(document.getElementsByTagName("link")).filter(function(e){return-1!=e.rel.indexOf("style")&&e.title})}function u(e){for(var t=c(),n=null,o=0;o<t.length;o++){var r=t[o];r.disabled=!0,r.title==e&&(n=r)}n?(n.disabled=!1,i.setCookie("haddock-style",e)):(t[0].disabled=!1,i.clearCookie("haddock-style"))}var d=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return r(t,e),t.prototype.render=function(t){return a("li",null,a("a",{href:"#",onClick:function(e){e.preventDefault(),t.onClick()}},t.title))},t}(l);var h=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return r(t,e),t.prototype.componentWillMount=function(){var t=this;document.addEventListener("mousedown",this.hide.bind(this)),document.addEventListener("keydown",function(e){t.state.isVisible&&"Escape"===e.key&&t.hide()})},t.prototype.hide=function(){this.setState({isVisible:!1})},t.prototype.show=function(){this.state.isVisible||this.setState({isVisible:!0})},t.prototype.toggleVisibility=function(){this.state.isVisible?this.hide():this.show()},t.prototype.componentDidMount=function(){this.props.showHideTrigger(this.toggleVisibility.bind(this))},t.prototype.render=function(e,t){var n=this;return a("div",{id:"style",class:t.isVisible?"":"hidden"},a("div",{id:"style-menu",class:"dropdown-menu",onMouseDown:function(e){e.stopPropagation()}},e.styles.map(function(t){return a("button",{type:"button",onClick:function(e){n.hide(),u(t)}},t)})))},t}(l);n.init=function(e){var t,n=c().map(function(e){return e.title});(t=i.getCookie("haddock-style"))&&u(t),s.render(a(h,{showHideTrigger:e||function(e){return function(e,t){if(1<e.length){var n=document.querySelector("#page-menu"),o=document.createElement("li");n.appendChild(o),s.render(a(d,{onClick:t,title:"Styles"}),n,o)}}(n,e)},styles:n}),document.body)}},{"./cookies":1,preact:7}],6:[function(e,t,n){var o,r;o=this,r=function(){return function(n){var o={};function r(e){if(o[e])return o[e].exports;var t=o[e]={i:e,l:!1,exports:{}};return n[e].call(t.exports,t,t.exports,r),t.l=!0,t.exports}return r.m=n,r.c=o,r.i=function(e){return e},r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:n})},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=8)}([function(e,t,n){"use strict";e.exports=function(e){return Array.isArray?Array.isArray(e):"[object Array]"===Object.prototype.toString.call(e)}},function(e,t,n){"use strict";var o=function(){function o(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(e,t,n){return t&&o(e.prototype,t),n&&o(e,n),e}}();var u=n(5),d=n(7),_=n(4),r=function(){function y(e,t){var n=t.location,o=void 0===n?0:n,r=t.distance,i=void 0===r?100:r,s=t.threshold,a=void 0===s?.6:s,l=t.maxPatternLength,c=void 0===l?32:l,u=t.isCaseSensitive,d=void 0!==u&&u,h=t.tokenSeparator,p=void 0===h?/ +/g:h,f=t.findAllMatches,v=void 0!==f&&f,g=t.minMatchCharLength,m=void 0===g?1:g;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,y),this.options={location:o,distance:i,threshold:a,maxPatternLength:c,isCaseSensitive:d,tokenSeparator:p,findAllMatches:v,minMatchCharLength:m},this.pattern=this.options.isCaseSensitive?e:e.toLowerCase(),this.pattern.length<=c&&(this.patternAlphabet=_(this.pattern))}return o(y,[{key:"search",value:function(e){if(this.options.isCaseSensitive||(e=e.toLowerCase()),this.pattern===e)return{isMatch:!0,score:0,matchedIndices:[[0,e.length-1]]};var t=this.options,n=t.maxPatternLength,o=t.tokenSeparator;if(this.pattern.length>n)return u(e,this.pattern,o);var r=this.options,i=r.location,s=r.distance,a=r.threshold,l=r.findAllMatches,c=r.minMatchCharLength;return d(e,this.pattern,this.patternAlphabet,{location:i,distance:s,threshold:a,findAllMatches:l,minMatchCharLength:c})}}]),y}();e.exports=r},function(e,t,n){"use strict";var u=n(0);e.exports=function(e,t){return function e(t,n,o){if(n){var r=n.indexOf("."),i=n,s=null;-1!==r&&(i=n.slice(0,r),s=n.slice(r+1));var a=t[i];if(null!=a)if(s||"string"!=typeof a&&"number"!=typeof a)if(u(a))for(var l=0,c=a.length;l<c;l+=1)e(a[l],s,o);else s&&e(a,s,o);else o.push(a.toString())}else o.push(t);return o}(e,t,[])}},function(e,t,n){"use strict";e.exports=function(){for(var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:[],t=1<arguments.length&&void 0!==arguments[1]?arguments[1]:1,n=[],o=-1,r=-1,i=0,s=e.length;i<s;i+=1){var a=e[i];a&&-1===o?o=i:a||-1===o||(t<=(r=i-1)-o+1&&n.push([o,r]),o=-1)}return e[i-1]&&t<=i-o&&n.push([o,i-1]),n}},function(e,t,n){"use strict";e.exports=function(e){for(var t={},n=e.length,o=0;o<n;o+=1)t[e.charAt(o)]=0;for(var r=0;r<n;r+=1)t[e.charAt(r)]|=1<<n-r-1;return t}},function(e,t,n){"use strict";var u=/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g;e.exports=function(e,t){var n=2<arguments.length&&void 0!==arguments[2]?arguments[2]:/ +/g,o=new RegExp(t.replace(u,"\\$&").replace(n,"|")),r=e.match(o),i=!!r,s=[];if(i)for(var a=0,l=r.length;a<l;a+=1){var c=r[a];s.push([e.indexOf(c),c.length-1])}return{score:i?.5:1,isMatch:i,matchedIndices:s}}},function(e,t,n){"use strict";e.exports=function(e,t){var n=t.errors,o=void 0===n?0:n,r=t.currentLocation,i=void 0===r?0:r,s=t.expectedLocation,a=void 0===s?0:s,l=t.distance,c=void 0===l?100:l,u=o/e.length,d=Math.abs(a-i);return c?u+d/c:d?1:u}},function(e,t,n){"use strict";var V=n(6),D=n(3);e.exports=function(e,t,n,o){for(var r=o.location,i=void 0===r?0:r,s=o.distance,a=void 0===s?100:s,l=o.threshold,c=void 0===l?.6:l,u=o.findAllMatches,d=void 0!==u&&u,h=o.minMatchCharLength,p=void 0===h?1:h,f=i,v=e.length,g=c,m=e.indexOf(t,f),y=t.length,_=[],b=0;b<v;b+=1)_[b]=0;if(-1!==m){var k=V(t,{errors:0,currentLocation:m,expectedLocation:f,distance:a});if(g=Math.min(k,g),-1!==(m=e.lastIndexOf(t,f+y))){var S=V(t,{errors:0,currentLocation:m,expectedLocation:f,distance:a});g=Math.min(S,g)}}m=-1;for(var x=[],w=1,C=y+v,L=1<<y-1,M=0;M<y;M+=1){for(var I=0,E=C;I<E;){V(t,{errors:M,currentLocation:f+E,expectedLocation:f,distance:a})<=g?I=E:C=E,E=Math.floor((C-I)/2+I)}C=E;var O=Math.max(1,f-E+1),A=d?v:Math.min(f+E,v)+y,T=Array(A+2);T[A+1]=(1<<M)-1;for(var N=A;O<=N;N-=1){var P=N-1,j=n[e.charAt(P)];if(j&&(_[P]=1),T[N]=(T[N+1]<<1|1)&j,0!==M&&(T[N]|=(x[N+1]|x[N])<<1|1|x[N+1]),T[N]&L&&(w=V(t,{errors:M,currentLocation:P,expectedLocation:f,distance:a}))<=g){if(g=w,(m=P)<=f)break;O=Math.max(1,2*f-m)}}if(g<V(t,{errors:M+1,currentLocation:f,expectedLocation:f,distance:a}))break;x=T}return{isMatch:0<=m,score:0===w?.001:w,matchedIndices:D(_,p)}}},function(e,t,n){"use strict";var o=function(){function o(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(e,t,n){return t&&o(e.prototype,t),n&&o(e,n),e}}();var i=n(1),R=n(2),V=n(0),r=function(){function U(e,t){var n=t.location,o=void 0===n?0:n,r=t.distance,i=void 0===r?100:r,s=t.threshold,a=void 0===s?.6:s,l=t.maxPatternLength,c=void 0===l?32:l,u=t.caseSensitive,d=void 0!==u&&u,h=t.tokenSeparator,p=void 0===h?/ +/g:h,f=t.findAllMatches,v=void 0!==f&&f,g=t.minMatchCharLength,m=void 0===g?1:g,y=t.id,_=void 0===y?null:y,b=t.keys,k=void 0===b?[]:b,S=t.shouldSort,x=void 0===S||S,w=t.getFn,C=void 0===w?R:w,L=t.sortFn,M=void 0===L?function(e,t){return e.score-t.score}:L,I=t.tokenize,E=void 0!==I&&I,O=t.matchAllTokens,A=void 0!==O&&O,T=t.includeMatches,N=void 0!==T&&T,P=t.includeScore,j=void 0!==P&&P,V=t.verbose,D=void 0!==V&&V;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,U),this.options={location:o,distance:i,threshold:a,maxPatternLength:c,isCaseSensitive:d,tokenSeparator:p,findAllMatches:v,minMatchCharLength:m,id:_,keys:k,includeMatches:N,includeScore:j,shouldSort:x,getFn:C,sortFn:M,verbose:D,tokenize:E,matchAllTokens:A},this.setCollection(e)}return o(U,[{key:"setCollection",value:function(e){return this.list=e}},{key:"search",value:function(e){this._log('---------\nSearch pattern: "'+e+'"');var t=this._prepareSearchers(e),n=t.tokenSearchers,o=t.fullSearcher,r=this._search(n,o),i=r.weights,s=r.results;return this._computeScore(i,s),this.options.shouldSort&&this._sort(s),this._format(s)}},{key:"_prepareSearchers",value:function(){var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:"",t=[];if(this.options.tokenize)for(var n=e.split(this.options.tokenSeparator),o=0,r=n.length;o<r;o+=1)t.push(new i(n[o],this.options));return{tokenSearchers:t,fullSearcher:new i(e,this.options)}}},{key:"_search",value:function(){var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:[],t=arguments[1],n=this.list,o={},r=[];if("string"==typeof n[0]){for(var i=0,s=n.length;i<s;i+=1)this._analyze({key:"",value:n[i],record:i,index:i},{resultMap:o,results:r,tokenSearchers:e,fullSearcher:t});return{weights:null,results:r}}for(var a={},l=0,c=n.length;l<c;l+=1)for(var u=n[l],d=0,h=this.options.keys.length;d<h;d+=1){var p=this.options.keys[d];if("string"!=typeof p){if(a[p.name]={weight:1-p.weight||1},p.weight<=0||1<p.weight)throw new Error("Key weight has to be > 0 and <= 1");p=p.name}else a[p]={weight:1};this._analyze({key:p,value:this.options.getFn(u,p),record:u,index:l},{resultMap:o,results:r,tokenSearchers:e,fullSearcher:t})}return{weights:a,results:r}}},{key:"_analyze",value:function(e,t){var n=e.key,o=e.arrayIndex,r=void 0===o?-1:o,i=e.value,s=e.record,a=e.index,l=t.tokenSearchers,c=void 0===l?[]:l,u=t.fullSearcher,d=void 0===u?[]:u,h=t.resultMap,p=void 0===h?{}:h,f=t.results,v=void 0===f?[]:f;if(null!=i){var g=!1,m=-1,y=0;if("string"==typeof i){this._log("\nKey: "+(""===n?"-":n));var _=d.search(i);if(this._log('Full text: "'+i+'", score: '+_.score),this.options.tokenize){for(var b=i.split(this.options.tokenSeparator),k=[],S=0;S<c.length;S+=1){var x=c[S];this._log('\nPattern: "'+x.pattern+'"');for(var w=!1,C=0;C<b.length;C+=1){var L=b[C],M=x.search(L),I={};M.isMatch?(I[L]=M.score,w=g=!0,k.push(M.score)):(I[L]=1,this.options.matchAllTokens||k.push(1)),this._log('Token: "'+L+'", score: '+I[L])}w&&(y+=1)}m=k[0];for(var E=k.length,O=1;O<E;O+=1)m+=k[O];m/=E,this._log("Token score average:",m)}var A=_.score;-1<m&&(A=(A+m)/2),this._log("Score average:",A);var T=!this.options.tokenize||!this.options.matchAllTokens||y>=c.length;if(this._log("\nCheck Matches: "+T),(g||_.isMatch)&&T){var N=p[a];N?N.output.push({key:n,arrayIndex:r,value:i,score:A,matchedIndices:_.matchedIndices}):(p[a]={item:s,output:[{key:n,arrayIndex:r,value:i,score:A,matchedIndices:_.matchedIndices}]},v.push(p[a]))}}else if(V(i))for(var P=0,j=i.length;P<j;P+=1)this._analyze({key:n,arrayIndex:P,value:i[P],record:s,index:a},{resultMap:p,results:v,tokenSearchers:c,fullSearcher:d})}}},{key:"_computeScore",value:function(e,t){this._log("\n\nComputing score:\n");for(var n=0,o=t.length;n<o;n+=1){for(var r=t[n].output,i=r.length,s=1,a=1,l=0;l<i;l+=1){var c=e?e[r[l].key].weight:1,u=(1===c?r[l].score:r[l].score||.001)*c;1!==c?a=Math.min(a,u):s*=r[l].nScore=u}t[n].score=1===a?s:a,this._log(t[n])}}},{key:"_sort",value:function(e){this._log("\n\nSorting...."),e.sort(this.options.sortFn)}},{key:"_format",value:function(e){var t=[];this.options.verbose&&this._log("\n\nOutput:\n\n",JSON.stringify(e));var n=[];this.options.includeMatches&&n.push(function(e,t){var n=e.output;t.matches=[];for(var o=0,r=n.length;o<r;o+=1){var i=n[o];if(0!==i.matchedIndices.length){var s={indices:i.matchedIndices,value:i.value};i.key&&(s.key=i.key),i.hasOwnProperty("arrayIndex")&&-1<i.arrayIndex&&(s.arrayIndex=i.arrayIndex),t.matches.push(s)}}}),this.options.includeScore&&n.push(function(e,t){t.score=e.score});for(var o=0,r=e.length;o<r;o+=1){var i=e[o];if(this.options.id&&(i.item=this.options.getFn(i.item,this.options.id)[0]),n.length){for(var s={item:i.item},a=0,l=n.length;a<l;a+=1)n[a](i,s);t.push(s)}else t.push(i.item)}return t}},{key:"_log",value:function(){var e;this.options.verbose&&(e=console).log.apply(e,arguments)}}]),U}();e.exports=r}])},"object"==typeof n&&"object"==typeof t?t.exports=r():"function"==typeof define&&define.amd?define("Fuse",[],r):"object"==typeof n?n.Fuse=r():o.Fuse=r()},{}],7:[function(e,y,t){!function(){"use strict";function n(e,t){var n,o,r,i,s=d;for(i=arguments.length;2<i--;)u.push(arguments[i]);for(t&&null!=t.children&&(u.length||u.push(t.children),delete t.children);u.length;)if((o=u.pop())&&void 0!==o.pop)for(i=o.length;i--;)u.push(o[i]);else"boolean"==typeof o&&(o=null),(r="function"!=typeof e)&&(null==o?o="":"number"==typeof o?o=String(o):"string"!=typeof o&&(r=!1)),r&&n?s[s.length-1]+=o:s===d?s=[o]:s.push(o),n=r;var a=new c;return a.nodeName=e,a.children=s,a.attributes=null==t?void 0:t,a.key=null==t?void 0:t.key,void 0!==D.vnode&&D.vnode(a),a}function L(e,t){for(var n in t)e[n]=t[n];return e}function i(e){!e.__d&&(e.__d=!0)&&1==p.push(e)&&(D.debounceRendering||r)(t)}function t(){var e,t=p;for(p=[];e=t.pop();)e.__d&&j(e)}function C(e,t){return e.__n===t||e.nodeName.toLowerCase()===t.toLowerCase()}function M(e){var t=L({},e.attributes);t.children=e.children;var n=e.nodeName.defaultProps;if(void 0!==n)for(var o in n)void 0===t[o]&&(t[o]=n[o]);return t}function I(e){var t=e.parentNode;t&&t.removeChild(e)}function v(e,t,n,o,r){if("className"===t&&(t="class"),"key"===t);else if("ref"===t)n&&n(null),o&&o(e);else if("class"!==t||r)if("style"===t){if(o&&"string"!=typeof o&&"string"!=typeof n||(e.style.cssText=o||""),o&&"object"==typeof o){if("string"!=typeof n)for(var i in n)i in o||(e.style[i]="");for(var i in o)e.style[i]="number"==typeof o[i]&&!1===h.test(i)?o[i]+"px":o[i]}}else if("dangerouslySetInnerHTML"===t)o&&(e.innerHTML=o.__html||"");else if("o"==t[0]&&"n"==t[1]){var s=t!==(t=t.replace(/Capture$/,""));t=t.toLowerCase().substring(2),o?n||e.addEventListener(t,l,s):e.removeEventListener(t,l,s),(e.__l||(e.__l={}))[t]=o}else if("list"!==t&&"type"!==t&&!r&&t in e){try{e[t]=null==o?"":o}catch(e){}null!=o&&!1!==o||"spellcheck"==t||e.removeAttribute(t)}else{var a=r&&t!==(t=t.replace(/^xlink:?/,""));null==o||!1===o?a?e.removeAttributeNS("http://www.w3.org/1999/xlink",t.toLowerCase()):e.removeAttribute(t):"function"!=typeof o&&(a?e.setAttributeNS("http://www.w3.org/1999/xlink",t.toLowerCase(),o):e.setAttribute(t,o))}else e.className=o||""}function l(e){return this.__l[e.type](D.event&&D.event(e)||e)}function E(){for(var e;e=U.pop();)D.afterMount&&D.afterMount(e),e.componentDidMount&&e.componentDidMount()}function O(e,t,n,o,r,i){R++||(g=null!=r&&void 0!==r.ownerSVGElement,m=null!=e&&!("__preactattr_"in e));var s=A(e,t,n,o,i);return r&&s.parentNode!==r&&r.appendChild(s),--R||(m=!1,i||E()),s}function A(e,t,n,o,r){var i=e,s=g;if(null!=t&&"boolean"!=typeof t||(t=""),"string"==typeof t||"number"==typeof t)return e&&void 0!==e.splitText&&e.parentNode&&(!e._component||r)?e.nodeValue!=t&&(e.nodeValue=t):(i=document.createTextNode(t),e&&(e.parentNode&&e.parentNode.replaceChild(i,e),T(e,!0))),i.__preactattr_=!0,i;var a,l,c=t.nodeName;if("function"==typeof c)return function(e,t,n,o){var r=e&&e._component,i=r,s=e,a=r&&e._componentConstructor===t.nodeName,l=a,c=M(t);for(;r&&!l&&(r=r.__u);)l=r.constructor===t.nodeName;r&&l&&(!o||r._component)?(P(r,c,3,n,o),e=r.base):(i&&!a&&(V(i),e=s=null),r=N(t.nodeName,c,n),e&&!r.__b&&(r.__b=e,s=null),P(r,c,1,n,o),e=r.base,s&&e!==s&&(s._component=null,T(s,!1)));return e}(e,t,n,o);if(g="svg"===c||"foreignObject"!==c&&g,c=String(c),(!e||!C(e,c))&&(a=c,(l=g?document.createElementNS("http://www.w3.org/2000/svg",a):document.createElement(a)).__n=a,i=l,e)){for(;e.firstChild;)i.appendChild(e.firstChild);e.parentNode&&e.parentNode.replaceChild(i,e),T(e,!0)}var u=i.firstChild,d=i.__preactattr_,h=t.children;if(null==d){d=i.__preactattr_={};for(var p=i.attributes,f=p.length;f--;)d[p[f].name]=p[f].value}return!m&&h&&1===h.length&&"string"==typeof h[0]&&null!=u&&void 0!==u.splitText&&null==u.nextSibling?u.nodeValue!=h[0]&&(u.nodeValue=h[0]):(h&&h.length||null!=u)&&function(e,t,n,o,r){var i,s,a,l,c,u=e.childNodes,d=[],h={},p=0,f=0,v=u.length,g=0,m=t?t.length:0;if(0!==v)for(var y=0;y<v;y++){var _=u[y],b=_.__preactattr_,k=m&&b?_._component?_._component.__k:b.key:null;null!=k?(p++,h[k]=_):(b||(void 0!==_.splitText?!r||_.nodeValue.trim():r))&&(d[g++]=_)}if(0!==m)for(var y=0;y<m;y++){l=t[y],c=null;var k=l.key;if(null!=k)p&&void 0!==h[k]&&(c=h[k],h[k]=void 0,p--);else if(f<g)for(i=f;i<g;i++)if(void 0!==d[i]&&(S=s=d[i],w=r,"string"==typeof(x=l)||"number"==typeof x?void 0!==S.splitText:"string"==typeof x.nodeName?!S._componentConstructor&&C(S,x.nodeName):w||S._componentConstructor===x.nodeName)){c=s,d[i]=void 0,i===g-1&&g--,i===f&&f++;break}c=A(c,l,n,o),a=u[y],c&&c!==e&&c!==a&&(null==a?e.appendChild(c):c===a.nextSibling?I(a):e.insertBefore(c,a))}var S,x,w;if(p)for(var y in h)void 0!==h[y]&&T(h[y],!1);for(;f<=g;)void 0!==(c=d[g--])&&T(c,!1)}(i,h,n,o,m||null!=d.dangerouslySetInnerHTML),function(e,t,n){var o;for(o in n)t&&null!=t[o]||null==n[o]||v(e,o,n[o],n[o]=void 0,g);for(o in t)"children"===o||"innerHTML"===o||o in n&&t[o]===("value"===o||"checked"===o?e[o]:n[o])||v(e,o,n[o],n[o]=t[o],g)}(i,t.attributes,d),g=s,i}function T(e,t){var n=e._component;n?V(n):(null!=e.__preactattr_&&e.__preactattr_.ref&&e.__preactattr_.ref(null),!1!==t&&null!=e.__preactattr_||I(e),o(e))}function o(e){for(e=e.lastChild;e;){var t=e.previousSibling;T(e,!0),e=t}}function N(e,t,n){var o,r=f.length;for(e.prototype&&e.prototype.render?(o=new e(t,n),a.call(o,t,n)):((o=new a(t,n)).constructor=e,o.render=s);r--;)if(f[r].constructor===e)return o.__b=f[r].__b,f.splice(r,1),o;return o}function s(e,t,n){return this.constructor(e,n)}function P(e,t,n,o,r){e.__x||(e.__x=!0,e.__r=t.ref,e.__k=t.key,delete t.ref,delete t.key,void 0===e.constructor.getDerivedStateFromProps&&(!e.base||r?e.componentWillMount&&e.componentWillMount():e.componentWillReceiveProps&&e.componentWillReceiveProps(t,o)),o&&o!==e.context&&(e.__c||(e.__c=e.context),e.context=o),e.__p||(e.__p=e.props),e.props=t,e.__x=!1,0!==n&&(1!==n&&!1===D.syncComponentUpdates&&e.base?i(e):j(e,1,r)),e.__r&&e.__r(e))}function j(e,t,n,o){if(!e.__x){var r,i,s,a=e.props,l=e.state,c=e.context,u=e.__p||a,d=e.__s||l,h=e.__c||c,p=e.base,f=e.__b,v=p||f,g=e._component,m=!1,y=h;if(e.constructor.getDerivedStateFromProps&&(l=L(L({},l),e.constructor.getDerivedStateFromProps(a,l)),e.state=l),p&&(e.props=u,e.state=d,e.context=h,2!==t&&e.shouldComponentUpdate&&!1===e.shouldComponentUpdate(a,l,c)?m=!0:e.componentWillUpdate&&e.componentWillUpdate(a,l,c),e.props=a,e.state=l,e.context=c),e.__p=e.__s=e.__c=e.__b=null,e.__d=!1,!m){r=e.render(a,l,c),e.getChildContext&&(c=L(L({},c),e.getChildContext())),p&&e.getSnapshotBeforeUpdate&&(y=e.getSnapshotBeforeUpdate(u,d));var _,b,k=r&&r.nodeName;if("function"==typeof k){var S=M(r);(i=g)&&i.constructor===k&&S.key==i.__k?P(i,S,1,c,!1):(_=i,e._component=i=N(k,S,c),i.__b=i.__b||f,i.__u=e,P(i,S,0,c,!1),j(i,1,n,!0)),b=i.base}else s=v,(_=g)&&(s=e._component=null),(v||1===t)&&(s&&(s._component=null),b=O(s,r,c,n||!p,v&&v.parentNode,!0));if(v&&b!==v&&i!==g){var x=v.parentNode;x&&b!==x&&(x.replaceChild(b,v),_||(v._component=null,T(v,!1)))}if(_&&V(_),(e.base=b)&&!o){for(var w=e,C=e;C=C.__u;)(w=C).base=b;b._component=w,b._componentConstructor=w.constructor}}for(!p||n?U.unshift(e):m||(e.componentDidUpdate&&e.componentDidUpdate(u,d,y),D.afterUpdate&&D.afterUpdate(e));e.__h.length;)e.__h.pop().call(e);R||o||E()}}function V(e){D.beforeUnmount&&D.beforeUnmount(e);var t=e.base;e.__x=!0,e.componentWillUnmount&&e.componentWillUnmount(),e.base=null;var n=e._component;n?V(n):t&&(t.__preactattr_&&t.__preactattr_.ref&&t.__preactattr_.ref(null),I(e.__b=t),f.push(e),o(t)),e.__r&&e.__r(null)}function a(e,t){this.__d=!0,this.context=t,this.props=e,this.state=this.state||{},this.__h=[]}var c=function(){},D={},u=[],d=[],r="function"==typeof Promise?Promise.resolve().then.bind(Promise.resolve()):setTimeout,h=/acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i,p=[],U=[],R=0,g=!1,m=!1,f=[];L(a.prototype,{setState:function(e,t){this.__s||(this.__s=this.state),this.state=L(L({},this.state),"function"==typeof e?e(this.state,this.props):e),t&&this.__h.push(t),i(this)},forceUpdate:function(e){e&&this.__h.push(e),j(this,2)},render:function(){}});var e={h:n,createElement:n,cloneElement:function(e,t){return n(e.nodeName,L(L({},e.attributes),t),2<arguments.length?[].slice.call(arguments,2):e.children)},Component:a,render:function(e,t,n){return O(n,e,{},!1,t,!1)},rerender:t,options:D};void 0!==y?y.exports=e:self.preact=e}()},{}]},{},[3]);
 //# sourceMappingURL=haddock-bundle.min.js.map
diff --git a/resources/html/quick-jump.min.js b/resources/html/quick-jump.min.js
--- a/resources/html/quick-jump.min.js
+++ b/resources/html/quick-jump.min.js
@@ -1,2 +1,2 @@
-!function i(s,a,l){function c(t,e){if(!a[t]){if(!s[t]){var n="function"==typeof require&&require;if(!e&&n)return n(t,!0);if(u)return u(t,!0);var o=new Error("Cannot find module '"+t+"'");throw o.code="MODULE_NOT_FOUND",o}var r=a[t]={exports:{}};s[t][0].call(r.exports,function(e){return c(s[t][1][e]||e)},r,r.exports,i,s,a,l)}return a[t].exports}for(var u="function"==typeof require&&require,e=0;e<l.length;e++)c(l[e]);return c}({1:[function(e,t,n){"use strict";var o,r=this&&this.__extends||(o=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},function(e,t){function n(){this.constructor=e}o(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)});Object.defineProperty(n,"__esModule",{value:!0});var i=e("fuse.js"),s=e("preact"),a=s.h,l=s.Component;var c=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return r(t,e),t.prototype.render=function(t){return a("li",null,a("a",{href:"#",onClick:function(e){e.preventDefault(),t.onClick()}},t.title))},t}(l);function u(e){var t=document.querySelector("#page-menu"),n=document.createElement("li");t.insertBefore(n,t.firstChild),s.render(a(c,{onClick:e,title:"Quick Jump"}),t,n)}function h(e,t){return t.length<=e?t:t.slice(0,e)}var p=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.linkIndex=0,e.focusPlease=!1,e.navigatedByKeyboard=!1,e}return r(e,t),e.prototype.componentWillMount=function(){var e,t,n,o,r=this;this.setState({searchString:"",isVisible:!1,expanded:{},activeLinkIndex:-1,moduleResults:[]}),e=this.props.baseUrl+"/doc-index.json",t=function(e){r.setState({fuse:new i(e,{threshold:.25,caseSensitive:!0,includeScore:!0,tokenize:!0,keys:[{name:"name",weight:.7},{name:"module",weight:.3}]}),moduleResults:[]})},n=function(e){console&&console.error("could not load 'doc-index.json' for searching",e),r.setState({failedLoading:!0})},(o=new XMLHttpRequest).onreadystatechange=function(){if(o.readyState===XMLHttpRequest.DONE)if(200===o.status){if(t)try{t(JSON.parse(o.responseText))}catch(e){n(o)}}else n&&n(o)},o.open("GET",e,!0),o.send(),document.addEventListener("mousedown",this.hide.bind(this)),document.addEventListener("keydown",function(e){r.state.isVisible&&("Escape"===e.key?r.hide():"ArrowUp"===e.key||"k"===e.key&&e.ctrlKey?(e.preventDefault(),r.navigateLinks(-1)):"ArrowDown"===e.key||"j"===e.key&&e.ctrlKey?(e.preventDefault(),r.navigateLinks(1)):"Enter"===e.key&&0<=r.state.activeLinkIndex&&r.followActiveLink()),"s"===e.key&&"input"!==e.target.tagName.toLowerCase()&&(e.preventDefault(),r.show())})},e.prototype.hide=function(){this.setState({isVisible:!1,searchString:""})},e.prototype.show=function(){this.state.isVisible||(this.focusPlease=!0,this.setState({isVisible:!0,activeLinkIndex:-1}))},e.prototype.toggleVisibility=function(){this.state.isVisible?this.hide():this.show()},e.prototype.navigateLinks=function(e){var t=Math.max(-1,Math.min(this.linkIndex-1,this.state.activeLinkIndex+e));this.navigatedByKeyboard=!0,this.setState({activeLinkIndex:t})},e.prototype.followActiveLink=function(){this.activeLinkAction&&this.activeLinkAction()},e.prototype.updateResults=function(){var e=this.input&&this.input.value||"",t=this.state.fuse.search(e),o={};t.forEach(function(e){var t=e.item.module;(o[t]||(o[t]=[])).push(e)});var r=[],n=function(e){var t=o[e],n=0;t.forEach(function(e){n+=1/e.score}),r.push({module:e,totalScore:1/n,items:t})};for(var i in o)n(i);r.sort(function(e,t){return e.totalScore-t.totalScore}),this.setState({searchString:e,isVisible:!0,moduleResults:r})},e.prototype.componentDidUpdate=function(){if(this.searchResults&&this.activeLink&&this.navigatedByKeyboard){var e=this.activeLink.getClientRects()[0],t=this.searchResults.getClientRects()[0].top;e.bottom>window.innerHeight?this.searchResults.scrollTop+=e.bottom-window.innerHeight+80:e.top<t&&(this.searchResults.scrollTop-=t-e.top+80)}this.focusPlease&&this.input&&this.input.focus(),this.navigatedByKeyboard=!1,this.focusPlease=!1},e.prototype.componentDidMount=function(){this.props.showHideTrigger(this.toggleVisibility.bind(this))},e.prototype.render=function(e,t){var r=this;if(t.failedLoading){var n="file:"==window.location.protocol;return a("div",{id:"search",class:t.isVisible?"":"hidden"},a("div",{id:"search-results"},a("p",{class:"error"},"Failed to load file 'doc-index.json' containing definitions in this package."),n?a("p",{class:"error"},"To use quick jump, load this page with HTTP (from a local static file web server) instead of using the ",a("code",null,"file://")," protocol. (For security reasons, it is not possible to fetch auxiliary files using JS in a HTML page opened with ",a("code",null,"file://"),".)"):[]))}this.linkIndex=0;var o=function(e){e.stopPropagation()},i=h(10,t.moduleResults).map(function(e){return r.renderResultsInModule(e)});return a("div",{id:"search",class:t.isVisible?"":"hidden"},a("div",{id:"search-form",onMouseDown:o},a("input",{placeholder:"Search in package by name",ref:function(e){r.input=e},onFocus:this.show.bind(this),onClick:this.show.bind(this),onInput:this.updateResults.bind(this)})),a("div",{id:"search-results",ref:function(e){r.searchResults=e},onMouseDown:o,onMouseOver:function(e){for(var t=e.target;t&&"function"==typeof t.getAttribute;){var n=t.getAttribute("data-link-index");if("string"==typeof n){var o=parseInt(n,10);r.setState({activeLinkIndex:o});break}t=t.parentNode}}},""===t.searchString?[a(v,null),a(f,null)]:0==i.length?a(g,{searchString:t.searchString}):a("ul",null,i)))},e.prototype.renderResultsInModule=function(e){var n=this,t=e.items,o=e.module,r=this.state.expanded[o]||t.length<=10,i=r?t:h(8,t);return a("li",{class:"search-module"},a("h4",null,o),a("ul",null,i.map(function(e){return t=e.item,a("li",{class:"search-result"},n.navigationLink(n.props.baseUrl+"/"+t.link,{},a(d,{html:t.display_html})));var t}),r?[]:a("li",{class:"more-results"},this.actionLink(function(){var e=Object.assign({},n.state.expanded);e[o]=!0,n.setState({expanded:e})},{},"show "+(t.length-i.length)+" more results from this module"))))},e.prototype.navigationLink=function(e,t){for(var n=this,o=[],r=2;r<arguments.length;r++)o[r-2]=arguments[r];var i=Object.assign({href:e,onClick:this.hide.bind(this)},t);return this.menuLink.apply(this,[i,function(){window.location.href=e,n.hide()}].concat(o))},e.prototype.actionLink=function(t,e){for(var n=[],o=2;o<arguments.length;o++)n[o-2]=arguments[o];var r=Object.assign({href:"#",onClick:function(e){e.preventDefault(),t()}},e);return this.menuLink.apply(this,[r,t].concat(n))},e.prototype.menuLink=function(e,t){for(var n=this,o=[],r=2;r<arguments.length;r++)o[r-2]=arguments[r];var i=this.linkIndex;i===this.state.activeLinkIndex&&(e.class=(e.class?e.class+" ":"")+"active-link",e.ref=function(e){e&&(n.activeLink=e)},this.activeLinkAction=t);var s=Object.assign({"data-link-index":i},e);return this.linkIndex+=1,a.apply(void 0,["a",s].concat(o))},e}(l),d=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return r(t,e),t.prototype.shouldComponentUpdate=function(e){return this.props.html!==e.html},t.prototype.render=function(e){return a("div",{dangerouslySetInnerHTML:{__html:e.html}})},t}(l);function f(){return a("table",{class:"keyboard-shortcuts"},a("tr",null,a("th",null,"Key"),a("th",null,"Shortcut")),a("tr",null,a("td",null,a("span",{class:"key"},"s")),a("td",null,"Open this search box")),a("tr",null,a("td",null,a("span",{class:"key"},"esc")),a("td",null,"Close this search box")),a("tr",null,a("td",null,a("span",{class:"key"},"↓"),",",a("span",{class:"key"},"ctrl")," + ",a("span",{class:"key"},"j")),a("td",null,"Move down in search results")),a("tr",null,a("td",null,a("span",{class:"key"},"↑"),",",a("span",{class:"key"},"ctrl")," + ",a("span",{class:"key"},"k")),a("td",null,"Move up in search results")),a("tr",null,a("td",null,a("span",{class:"key"},"↵")),a("td",null,"Go to active search result")))}function v(){return a("p",null,"You can find any exported type, constructor, class, function or pattern defined in this package by (approximate) name.")}function g(e){var t=[a("p",null,"Your search for '",e.searchString,"' produced the following list of results: ",a("code",null,"[]"),"."),a("p",null,a("code",null,"Nothing")," matches your query for '",e.searchString,"'."),a("p",null,a("code",null,"Left \"no matches for '",e.searchString,"'\" :: Either String (NonEmpty SearchResult)"))];return t[(e.searchString||"a").charCodeAt(0)%t.length]}function _(e,t){s.render(a(p,{baseUrl:e||".",showHideTrigger:t||u}),document.body)}n.init=_,window.quickNav={init:_}},{"fuse.js":2,preact:3}],2:[function(e,t,n){var o,r;o=this,r=function(){return function(n){var o={};function r(e){if(o[e])return o[e].exports;var t=o[e]={i:e,l:!1,exports:{}};return n[e].call(t.exports,t,t.exports,r),t.l=!0,t.exports}return r.m=n,r.c=o,r.i=function(e){return e},r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:n})},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=8)}([function(e,t,n){"use strict";e.exports=function(e){return Array.isArray?Array.isArray(e):"[object Array]"===Object.prototype.toString.call(e)}},function(e,t,n){"use strict";var o=function(){function o(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(e,t,n){return t&&o(e.prototype,t),n&&o(e,n),e}}();var u=n(5),h=n(7),y=n(4),r=function(){function m(e,t){var n=t.location,o=void 0===n?0:n,r=t.distance,i=void 0===r?100:r,s=t.threshold,a=void 0===s?.6:s,l=t.maxPatternLength,c=void 0===l?32:l,u=t.isCaseSensitive,h=void 0!==u&&u,p=t.tokenSeparator,d=void 0===p?/ +/g:p,f=t.findAllMatches,v=void 0!==f&&f,g=t.minMatchCharLength,_=void 0===g?1:g;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,m),this.options={location:o,distance:i,threshold:a,maxPatternLength:c,isCaseSensitive:h,tokenSeparator:d,findAllMatches:v,minMatchCharLength:_},this.pattern=this.options.isCaseSensitive?e:e.toLowerCase(),this.pattern.length<=c&&(this.patternAlphabet=y(this.pattern))}return o(m,[{key:"search",value:function(e){if(this.options.isCaseSensitive||(e=e.toLowerCase()),this.pattern===e)return{isMatch:!0,score:0,matchedIndices:[[0,e.length-1]]};var t=this.options,n=t.maxPatternLength,o=t.tokenSeparator;if(this.pattern.length>n)return u(e,this.pattern,o);var r=this.options,i=r.location,s=r.distance,a=r.threshold,l=r.findAllMatches,c=r.minMatchCharLength;return h(e,this.pattern,this.patternAlphabet,{location:i,distance:s,threshold:a,findAllMatches:l,minMatchCharLength:c})}}]),m}();e.exports=r},function(e,t,n){"use strict";var u=n(0);e.exports=function(e,t){return function e(t,n,o){if(n){var r=n.indexOf("."),i=n,s=null;-1!==r&&(i=n.slice(0,r),s=n.slice(r+1));var a=t[i];if(null!=a)if(s||"string"!=typeof a&&"number"!=typeof a)if(u(a))for(var l=0,c=a.length;l<c;l+=1)e(a[l],s,o);else s&&e(a,s,o);else o.push(a.toString())}else o.push(t);return o}(e,t,[])}},function(e,t,n){"use strict";e.exports=function(){for(var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:[],t=1<arguments.length&&void 0!==arguments[1]?arguments[1]:1,n=[],o=-1,r=-1,i=0,s=e.length;i<s;i+=1){var a=e[i];a&&-1===o?o=i:a||-1===o||(t<=(r=i-1)-o+1&&n.push([o,r]),o=-1)}return e[i-1]&&t<=i-o&&n.push([o,i-1]),n}},function(e,t,n){"use strict";e.exports=function(e){for(var t={},n=e.length,o=0;o<n;o+=1)t[e.charAt(o)]=0;for(var r=0;r<n;r+=1)t[e.charAt(r)]|=1<<n-r-1;return t}},function(e,t,n){"use strict";var u=/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g;e.exports=function(e,t){var n=2<arguments.length&&void 0!==arguments[2]?arguments[2]:/ +/g,o=new RegExp(t.replace(u,"\\$&").replace(n,"|")),r=e.match(o),i=!!r,s=[];if(i)for(var a=0,l=r.length;a<l;a+=1){var c=r[a];s.push([e.indexOf(c),c.length-1])}return{score:i?.5:1,isMatch:i,matchedIndices:s}}},function(e,t,n){"use strict";e.exports=function(e,t){var n=t.errors,o=void 0===n?0:n,r=t.currentLocation,i=void 0===r?0:r,s=t.expectedLocation,a=void 0===s?0:s,l=t.distance,c=void 0===l?100:l,u=o/e.length,h=Math.abs(a-i);return c?u+h/c:h?1:u}},function(e,t,n){"use strict";var U=n(6),R=n(3);e.exports=function(e,t,n,o){for(var r=o.location,i=void 0===r?0:r,s=o.distance,a=void 0===s?100:s,l=o.threshold,c=void 0===l?.6:l,u=o.findAllMatches,h=void 0!==u&&u,p=o.minMatchCharLength,d=void 0===p?1:p,f=i,v=e.length,g=c,_=e.indexOf(t,f),m=t.length,y=[],k=0;k<v;k+=1)y[k]=0;if(-1!==_){var b=U(t,{errors:0,currentLocation:_,expectedLocation:f,distance:a});if(g=Math.min(b,g),-1!==(_=e.lastIndexOf(t,f+m))){var x=U(t,{errors:0,currentLocation:_,expectedLocation:f,distance:a});g=Math.min(x,g)}}_=-1;for(var S=[],w=1,L=m+v,C=1<<m-1,M=0;M<m;M+=1){for(var A=0,N=L;A<N;){U(t,{errors:M,currentLocation:f+N,expectedLocation:f,distance:a})<=g?A=N:L=N,N=Math.floor((L-A)/2+A)}L=N;var I=Math.max(1,f-N+1),T=h?v:Math.min(f+N,v)+m,O=Array(T+2);O[T+1]=(1<<M)-1;for(var P=T;I<=P;P-=1){var j=P-1,E=n[e.charAt(j)];if(E&&(y[j]=1),O[P]=(O[P+1]<<1|1)&E,0!==M&&(O[P]|=(S[P+1]|S[P])<<1|1|S[P+1]),O[P]&C&&(w=U(t,{errors:M,currentLocation:j,expectedLocation:f,distance:a}))<=g){if(g=w,(_=j)<=f)break;I=Math.max(1,2*f-_)}}if(g<U(t,{errors:M+1,currentLocation:f,expectedLocation:f,distance:a}))break;S=O}return{isMatch:0<=_,score:0===w?.001:w,matchedIndices:R(y,d)}}},function(e,t,n){"use strict";var o=function(){function o(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(e,t,n){return t&&o(e.prototype,t),n&&o(e,n),e}}();var i=n(1),F=n(2),U=n(0),r=function(){function D(e,t){var n=t.location,o=void 0===n?0:n,r=t.distance,i=void 0===r?100:r,s=t.threshold,a=void 0===s?.6:s,l=t.maxPatternLength,c=void 0===l?32:l,u=t.caseSensitive,h=void 0!==u&&u,p=t.tokenSeparator,d=void 0===p?/ +/g:p,f=t.findAllMatches,v=void 0!==f&&f,g=t.minMatchCharLength,_=void 0===g?1:g,m=t.id,y=void 0===m?null:m,k=t.keys,b=void 0===k?[]:k,x=t.shouldSort,S=void 0===x||x,w=t.getFn,L=void 0===w?F:w,C=t.sortFn,M=void 0===C?function(e,t){return e.score-t.score}:C,A=t.tokenize,N=void 0!==A&&A,I=t.matchAllTokens,T=void 0!==I&&I,O=t.includeMatches,P=void 0!==O&&O,j=t.includeScore,E=void 0!==j&&j,U=t.verbose,R=void 0!==U&&U;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,D),this.options={location:o,distance:i,threshold:a,maxPatternLength:c,isCaseSensitive:h,tokenSeparator:d,findAllMatches:v,minMatchCharLength:_,id:y,keys:b,includeMatches:P,includeScore:E,shouldSort:S,getFn:L,sortFn:M,verbose:R,tokenize:N,matchAllTokens:T},this.setCollection(e)}return o(D,[{key:"setCollection",value:function(e){return this.list=e}},{key:"search",value:function(e){this._log('---------\nSearch pattern: "'+e+'"');var t=this._prepareSearchers(e),n=t.tokenSearchers,o=t.fullSearcher,r=this._search(n,o),i=r.weights,s=r.results;return this._computeScore(i,s),this.options.shouldSort&&this._sort(s),this._format(s)}},{key:"_prepareSearchers",value:function(){var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:"",t=[];if(this.options.tokenize)for(var n=e.split(this.options.tokenSeparator),o=0,r=n.length;o<r;o+=1)t.push(new i(n[o],this.options));return{tokenSearchers:t,fullSearcher:new i(e,this.options)}}},{key:"_search",value:function(){var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:[],t=arguments[1],n=this.list,o={},r=[];if("string"==typeof n[0]){for(var i=0,s=n.length;i<s;i+=1)this._analyze({key:"",value:n[i],record:i,index:i},{resultMap:o,results:r,tokenSearchers:e,fullSearcher:t});return{weights:null,results:r}}for(var a={},l=0,c=n.length;l<c;l+=1)for(var u=n[l],h=0,p=this.options.keys.length;h<p;h+=1){var d=this.options.keys[h];if("string"!=typeof d){if(a[d.name]={weight:1-d.weight||1},d.weight<=0||1<d.weight)throw new Error("Key weight has to be > 0 and <= 1");d=d.name}else a[d]={weight:1};this._analyze({key:d,value:this.options.getFn(u,d),record:u,index:l},{resultMap:o,results:r,tokenSearchers:e,fullSearcher:t})}return{weights:a,results:r}}},{key:"_analyze",value:function(e,t){var n=e.key,o=e.arrayIndex,r=void 0===o?-1:o,i=e.value,s=e.record,a=e.index,l=t.tokenSearchers,c=void 0===l?[]:l,u=t.fullSearcher,h=void 0===u?[]:u,p=t.resultMap,d=void 0===p?{}:p,f=t.results,v=void 0===f?[]:f;if(null!=i){var g=!1,_=-1,m=0;if("string"==typeof i){this._log("\nKey: "+(""===n?"-":n));var y=h.search(i);if(this._log('Full text: "'+i+'", score: '+y.score),this.options.tokenize){for(var k=i.split(this.options.tokenSeparator),b=[],x=0;x<c.length;x+=1){var S=c[x];this._log('\nPattern: "'+S.pattern+'"');for(var w=!1,L=0;L<k.length;L+=1){var C=k[L],M=S.search(C),A={};M.isMatch?(A[C]=M.score,w=g=!0,b.push(M.score)):(A[C]=1,this.options.matchAllTokens||b.push(1)),this._log('Token: "'+C+'", score: '+A[C])}w&&(m+=1)}_=b[0];for(var N=b.length,I=1;I<N;I+=1)_+=b[I];_/=N,this._log("Token score average:",_)}var T=y.score;-1<_&&(T=(T+_)/2),this._log("Score average:",T);var O=!this.options.tokenize||!this.options.matchAllTokens||m>=c.length;if(this._log("\nCheck Matches: "+O),(g||y.isMatch)&&O){var P=d[a];P?P.output.push({key:n,arrayIndex:r,value:i,score:T,matchedIndices:y.matchedIndices}):(d[a]={item:s,output:[{key:n,arrayIndex:r,value:i,score:T,matchedIndices:y.matchedIndices}]},v.push(d[a]))}}else if(U(i))for(var j=0,E=i.length;j<E;j+=1)this._analyze({key:n,arrayIndex:j,value:i[j],record:s,index:a},{resultMap:d,results:v,tokenSearchers:c,fullSearcher:h})}}},{key:"_computeScore",value:function(e,t){this._log("\n\nComputing score:\n");for(var n=0,o=t.length;n<o;n+=1){for(var r=t[n].output,i=r.length,s=1,a=1,l=0;l<i;l+=1){var c=e?e[r[l].key].weight:1,u=(1===c?r[l].score:r[l].score||.001)*c;1!==c?a=Math.min(a,u):s*=r[l].nScore=u}t[n].score=1===a?s:a,this._log(t[n])}}},{key:"_sort",value:function(e){this._log("\n\nSorting...."),e.sort(this.options.sortFn)}},{key:"_format",value:function(e){var t=[];this.options.verbose&&this._log("\n\nOutput:\n\n",JSON.stringify(e));var n=[];this.options.includeMatches&&n.push(function(e,t){var n=e.output;t.matches=[];for(var o=0,r=n.length;o<r;o+=1){var i=n[o];if(0!==i.matchedIndices.length){var s={indices:i.matchedIndices,value:i.value};i.key&&(s.key=i.key),i.hasOwnProperty("arrayIndex")&&-1<i.arrayIndex&&(s.arrayIndex=i.arrayIndex),t.matches.push(s)}}}),this.options.includeScore&&n.push(function(e,t){t.score=e.score});for(var o=0,r=e.length;o<r;o+=1){var i=e[o];if(this.options.id&&(i.item=this.options.getFn(i.item,this.options.id)[0]),n.length){for(var s={item:i.item},a=0,l=n.length;a<l;a+=1)n[a](i,s);t.push(s)}else t.push(i.item)}return t}},{key:"_log",value:function(){var e;this.options.verbose&&(e=console).log.apply(e,arguments)}}]),D}();e.exports=r}])},"object"==typeof n&&"object"==typeof t?t.exports=r():"function"==typeof define&&define.amd?define("Fuse",[],r):"object"==typeof n?n.Fuse=r():o.Fuse=r()},{}],3:[function(e,m,t){!function(){"use strict";function n(e,t){var n,o,r,i,s=h;for(i=arguments.length;2<i--;)u.push(arguments[i]);for(t&&null!=t.children&&(u.length||u.push(t.children),delete t.children);u.length;)if((o=u.pop())&&void 0!==o.pop)for(i=o.length;i--;)u.push(o[i]);else"boolean"==typeof o&&(o=null),(r="function"!=typeof e)&&(null==o?o="":"number"==typeof o?o=String(o):"string"!=typeof o&&(r=!1)),r&&n?s[s.length-1]+=o:s===h?s=[o]:s.push(o),n=r;var a=new c;return a.nodeName=e,a.children=s,a.attributes=null==t?void 0:t,a.key=null==t?void 0:t.key,void 0!==R.vnode&&R.vnode(a),a}function C(e,t){for(var n in t)e[n]=t[n];return e}function i(e){!e.__d&&(e.__d=!0)&&1==d.push(e)&&(R.debounceRendering||r)(t)}function t(){var e,t=d;for(d=[];e=t.pop();)e.__d&&E(e)}function L(e,t){return e.__n===t||e.nodeName.toLowerCase()===t.toLowerCase()}function M(e){var t=C({},e.attributes);t.children=e.children;var n=e.nodeName.defaultProps;if(void 0!==n)for(var o in n)void 0===t[o]&&(t[o]=n[o]);return t}function A(e){var t=e.parentNode;t&&t.removeChild(e)}function v(e,t,n,o,r){if("className"===t&&(t="class"),"key"===t);else if("ref"===t)n&&n(null),o&&o(e);else if("class"!==t||r)if("style"===t){if(o&&"string"!=typeof o&&"string"!=typeof n||(e.style.cssText=o||""),o&&"object"==typeof o){if("string"!=typeof n)for(var i in n)i in o||(e.style[i]="");for(var i in o)e.style[i]="number"==typeof o[i]&&!1===p.test(i)?o[i]+"px":o[i]}}else if("dangerouslySetInnerHTML"===t)o&&(e.innerHTML=o.__html||"");else if("o"==t[0]&&"n"==t[1]){var s=t!==(t=t.replace(/Capture$/,""));t=t.toLowerCase().substring(2),o?n||e.addEventListener(t,l,s):e.removeEventListener(t,l,s),(e.__l||(e.__l={}))[t]=o}else if("list"!==t&&"type"!==t&&!r&&t in e){try{e[t]=null==o?"":o}catch(e){}null!=o&&!1!==o||"spellcheck"==t||e.removeAttribute(t)}else{var a=r&&t!==(t=t.replace(/^xlink:?/,""));null==o||!1===o?a?e.removeAttributeNS("http://www.w3.org/1999/xlink",t.toLowerCase()):e.removeAttribute(t):"function"!=typeof o&&(a?e.setAttributeNS("http://www.w3.org/1999/xlink",t.toLowerCase(),o):e.setAttribute(t,o))}else e.className=o||""}function l(e){return this.__l[e.type](R.event&&R.event(e)||e)}function N(){for(var e;e=D.pop();)R.afterMount&&R.afterMount(e),e.componentDidMount&&e.componentDidMount()}function I(e,t,n,o,r,i){F++||(g=null!=r&&void 0!==r.ownerSVGElement,_=null!=e&&!("__preactattr_"in e));var s=T(e,t,n,o,i);return r&&s.parentNode!==r&&r.appendChild(s),--F||(_=!1,i||N()),s}function T(e,t,n,o,r){var i=e,s=g;if(null!=t&&"boolean"!=typeof t||(t=""),"string"==typeof t||"number"==typeof t)return e&&void 0!==e.splitText&&e.parentNode&&(!e._component||r)?e.nodeValue!=t&&(e.nodeValue=t):(i=document.createTextNode(t),e&&(e.parentNode&&e.parentNode.replaceChild(i,e),O(e,!0))),i.__preactattr_=!0,i;var a,l,c=t.nodeName;if("function"==typeof c)return function(e,t,n,o){var r=e&&e._component,i=r,s=e,a=r&&e._componentConstructor===t.nodeName,l=a,c=M(t);for(;r&&!l&&(r=r.__u);)l=r.constructor===t.nodeName;r&&l&&(!o||r._component)?(j(r,c,3,n,o),e=r.base):(i&&!a&&(U(i),e=s=null),r=P(t.nodeName,c,n),e&&!r.__b&&(r.__b=e,s=null),j(r,c,1,n,o),e=r.base,s&&e!==s&&(s._component=null,O(s,!1)));return e}(e,t,n,o);if(g="svg"===c||"foreignObject"!==c&&g,c=String(c),(!e||!L(e,c))&&(a=c,(l=g?document.createElementNS("http://www.w3.org/2000/svg",a):document.createElement(a)).__n=a,i=l,e)){for(;e.firstChild;)i.appendChild(e.firstChild);e.parentNode&&e.parentNode.replaceChild(i,e),O(e,!0)}var u=i.firstChild,h=i.__preactattr_,p=t.children;if(null==h){h=i.__preactattr_={};for(var d=i.attributes,f=d.length;f--;)h[d[f].name]=d[f].value}return!_&&p&&1===p.length&&"string"==typeof p[0]&&null!=u&&void 0!==u.splitText&&null==u.nextSibling?u.nodeValue!=p[0]&&(u.nodeValue=p[0]):(p&&p.length||null!=u)&&function(e,t,n,o,r){var i,s,a,l,c,u=e.childNodes,h=[],p={},d=0,f=0,v=u.length,g=0,_=t?t.length:0;if(0!==v)for(var m=0;m<v;m++){var y=u[m],k=y.__preactattr_,b=_&&k?y._component?y._component.__k:k.key:null;null!=b?(d++,p[b]=y):(k||(void 0!==y.splitText?!r||y.nodeValue.trim():r))&&(h[g++]=y)}if(0!==_)for(var m=0;m<_;m++){l=t[m],c=null;var b=l.key;if(null!=b)d&&void 0!==p[b]&&(c=p[b],p[b]=void 0,d--);else if(f<g)for(i=f;i<g;i++)if(void 0!==h[i]&&(x=s=h[i],w=r,"string"==typeof(S=l)||"number"==typeof S?void 0!==x.splitText:"string"==typeof S.nodeName?!x._componentConstructor&&L(x,S.nodeName):w||x._componentConstructor===S.nodeName)){c=s,h[i]=void 0,i===g-1&&g--,i===f&&f++;break}c=T(c,l,n,o),a=u[m],c&&c!==e&&c!==a&&(null==a?e.appendChild(c):c===a.nextSibling?A(a):e.insertBefore(c,a))}var x,S,w;if(d)for(var m in p)void 0!==p[m]&&O(p[m],!1);for(;f<=g;)void 0!==(c=h[g--])&&O(c,!1)}(i,p,n,o,_||null!=h.dangerouslySetInnerHTML),function(e,t,n){var o;for(o in n)t&&null!=t[o]||null==n[o]||v(e,o,n[o],n[o]=void 0,g);for(o in t)"children"===o||"innerHTML"===o||o in n&&t[o]===("value"===o||"checked"===o?e[o]:n[o])||v(e,o,n[o],n[o]=t[o],g)}(i,t.attributes,h),g=s,i}function O(e,t){var n=e._component;n?U(n):(null!=e.__preactattr_&&e.__preactattr_.ref&&e.__preactattr_.ref(null),!1!==t&&null!=e.__preactattr_||A(e),o(e))}function o(e){for(e=e.lastChild;e;){var t=e.previousSibling;O(e,!0),e=t}}function P(e,t,n){var o,r=f.length;for(e.prototype&&e.prototype.render?(o=new e(t,n),a.call(o,t,n)):((o=new a(t,n)).constructor=e,o.render=s);r--;)if(f[r].constructor===e)return o.__b=f[r].__b,f.splice(r,1),o;return o}function s(e,t,n){return this.constructor(e,n)}function j(e,t,n,o,r){e.__x||(e.__x=!0,e.__r=t.ref,e.__k=t.key,delete t.ref,delete t.key,void 0===e.constructor.getDerivedStateFromProps&&(!e.base||r?e.componentWillMount&&e.componentWillMount():e.componentWillReceiveProps&&e.componentWillReceiveProps(t,o)),o&&o!==e.context&&(e.__c||(e.__c=e.context),e.context=o),e.__p||(e.__p=e.props),e.props=t,e.__x=!1,0!==n&&(1!==n&&!1===R.syncComponentUpdates&&e.base?i(e):E(e,1,r)),e.__r&&e.__r(e))}function E(e,t,n,o){if(!e.__x){var r,i,s,a=e.props,l=e.state,c=e.context,u=e.__p||a,h=e.__s||l,p=e.__c||c,d=e.base,f=e.__b,v=d||f,g=e._component,_=!1,m=p;if(e.constructor.getDerivedStateFromProps&&(l=C(C({},l),e.constructor.getDerivedStateFromProps(a,l)),e.state=l),d&&(e.props=u,e.state=h,e.context=p,2!==t&&e.shouldComponentUpdate&&!1===e.shouldComponentUpdate(a,l,c)?_=!0:e.componentWillUpdate&&e.componentWillUpdate(a,l,c),e.props=a,e.state=l,e.context=c),e.__p=e.__s=e.__c=e.__b=null,e.__d=!1,!_){r=e.render(a,l,c),e.getChildContext&&(c=C(C({},c),e.getChildContext())),d&&e.getSnapshotBeforeUpdate&&(m=e.getSnapshotBeforeUpdate(u,h));var y,k,b=r&&r.nodeName;if("function"==typeof b){var x=M(r);(i=g)&&i.constructor===b&&x.key==i.__k?j(i,x,1,c,!1):(y=i,e._component=i=P(b,x,c),i.__b=i.__b||f,i.__u=e,j(i,x,0,c,!1),E(i,1,n,!0)),k=i.base}else s=v,(y=g)&&(s=e._component=null),(v||1===t)&&(s&&(s._component=null),k=I(s,r,c,n||!d,v&&v.parentNode,!0));if(v&&k!==v&&i!==g){var S=v.parentNode;S&&k!==S&&(S.replaceChild(k,v),y||(v._component=null,O(v,!1)))}if(y&&U(y),(e.base=k)&&!o){for(var w=e,L=e;L=L.__u;)(w=L).base=k;k._component=w,k._componentConstructor=w.constructor}}for(!d||n?D.unshift(e):_||(e.componentDidUpdate&&e.componentDidUpdate(u,h,m),R.afterUpdate&&R.afterUpdate(e));e.__h.length;)e.__h.pop().call(e);F||o||N()}}function U(e){R.beforeUnmount&&R.beforeUnmount(e);var t=e.base;e.__x=!0,e.componentWillUnmount&&e.componentWillUnmount(),e.base=null;var n=e._component;n?U(n):t&&(t.__preactattr_&&t.__preactattr_.ref&&t.__preactattr_.ref(null),A(e.__b=t),f.push(e),o(t)),e.__r&&e.__r(null)}function a(e,t){this.__d=!0,this.context=t,this.props=e,this.state=this.state||{},this.__h=[]}var c=function(){},R={},u=[],h=[],r="function"==typeof Promise?Promise.resolve().then.bind(Promise.resolve()):setTimeout,p=/acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i,d=[],D=[],F=0,g=!1,_=!1,f=[];C(a.prototype,{setState:function(e,t){this.__s||(this.__s=this.state),this.state=C(C({},this.state),"function"==typeof e?e(this.state,this.props):e),t&&this.__h.push(t),i(this)},forceUpdate:function(e){e&&this.__h.push(e),E(this,2)},render:function(){}});var e={h:n,createElement:n,cloneElement:function(e,t){return n(e.nodeName,C(C({},e.attributes),t),2<arguments.length?[].slice.call(arguments,2):e.children)},Component:a,render:function(e,t,n){return I(n,e,{},!1,t,!1)},rerender:t,options:R};void 0!==m?m.exports=e:self.preact=e}()},{}]},{},[1]);
+!function i(s,a,l){function c(t,e){if(!a[t]){if(!s[t]){var n="function"==typeof require&&require;if(!e&&n)return n(t,!0);if(u)return u(t,!0);var o=new Error("Cannot find module '"+t+"'");throw o.code="MODULE_NOT_FOUND",o}var r=a[t]={exports:{}};s[t][0].call(r.exports,function(e){return c(s[t][1][e]||e)},r,r.exports,i,s,a,l)}return a[t].exports}for(var u="function"==typeof require&&require,e=0;e<l.length;e++)c(l[e]);return c}({1:[function(e,t,n){"use strict";var o,r=this&&this.__extends||(o=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},function(e,t){function n(){this.constructor=e}o(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)});Object.defineProperty(n,"__esModule",{value:!0});var i=e("fuse.js"),s=e("preact"),a=s.h,l=s.Component;var c=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return r(t,e),t.prototype.render=function(t){return a("li",null,a("a",{href:"#",onClick:function(e){e.preventDefault(),t.onClick()}},t.title))},t}(l);function u(e,t){return t.length<=e?t:t.slice(0,e)}var h=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.linkIndex=0,e.focusPlease=!1,e.navigatedByKeyboard=!1,e}return r(e,t),e.prototype.componentWillMount=function(){var e,t,n,o,r=this;this.setState({searchString:"",isVisible:!1,expanded:{},activeLinkIndex:-1,moduleResults:[]}),e=this.props.baseUrl+"/doc-index.json",t=function(e){r.setState({fuse:new i(e,{threshold:.25,caseSensitive:!0,includeScore:!0,tokenize:!0,keys:[{name:"name",weight:.7},{name:"module",weight:.3}]}),moduleResults:[]})},n=function(e){console&&console.error("could not load 'doc-index.json' for searching",e),r.setState({failedLoading:!0})},(o=new XMLHttpRequest).onreadystatechange=function(){if(o.readyState===XMLHttpRequest.DONE)if(200===o.status){if(t)try{t(JSON.parse(o.responseText))}catch(e){n(o)}}else n&&n(o)},o.open("GET",e,!0),o.send(),document.addEventListener("mousedown",this.hide.bind(this)),document.addEventListener("keydown",function(e){r.state.isVisible&&("Escape"===e.key?r.hide():"ArrowUp"===e.key||"k"===e.key&&e.ctrlKey?(e.preventDefault(),r.navigateLinks(-1)):"ArrowDown"===e.key||"j"===e.key&&e.ctrlKey?(e.preventDefault(),r.navigateLinks(1)):"Enter"===e.key&&0<=r.state.activeLinkIndex&&r.followActiveLink()),"s"===e.key&&"input"!==e.target.tagName.toLowerCase()&&(e.preventDefault(),r.show())})},e.prototype.hide=function(){this.setState({isVisible:!1,searchString:""})},e.prototype.show=function(){this.state.isVisible||(this.focusPlease=!0,this.setState({isVisible:!0,activeLinkIndex:-1}))},e.prototype.toggleVisibility=function(){this.state.isVisible?this.hide():this.show()},e.prototype.navigateLinks=function(e){var t=Math.max(-1,Math.min(this.linkIndex-1,this.state.activeLinkIndex+e));this.navigatedByKeyboard=!0,this.setState({activeLinkIndex:t})},e.prototype.followActiveLink=function(){this.activeLinkAction&&this.activeLinkAction()},e.prototype.updateResults=function(){var e=this.input&&this.input.value||"",t=this.state.fuse.search(e),o={};t.forEach(function(e){var t=e.item.module;(o[t]||(o[t]=[])).push(e)});var r=[],n=function(e){var t=o[e],n=0;t.forEach(function(e){n+=1/e.score}),r.push({module:e,totalScore:1/n,items:t})};for(var i in o)n(i);r.sort(function(e,t){return e.totalScore-t.totalScore}),this.setState({searchString:e,isVisible:!0,moduleResults:r})},e.prototype.componentDidUpdate=function(){if(this.searchResults&&this.activeLink&&this.navigatedByKeyboard){var e=this.activeLink.getClientRects()[0],t=this.searchResults.getClientRects()[0].top;e.bottom>window.innerHeight?this.searchResults.scrollTop+=e.bottom-window.innerHeight+80:e.top<t&&(this.searchResults.scrollTop-=t-e.top+80)}this.focusPlease&&this.input&&this.input.focus(),this.navigatedByKeyboard=!1,this.focusPlease=!1},e.prototype.componentDidMount=function(){this.props.showHideTrigger(this.toggleVisibility.bind(this))},e.prototype.render=function(e,t){var r=this;if(t.failedLoading){var n="file:"==window.location.protocol;return a("div",{id:"search",class:t.isVisible?"":"hidden"},a("div",{id:"search-results"},a("p",{class:"error"},"Failed to load file 'doc-index.json' containing definitions in this package."),n?a("p",{class:"error"},"To use quick jump, load this page with HTTP (from a local static file web server) instead of using the ",a("code",null,"file://")," protocol. (For security reasons, it is not possible to fetch auxiliary files using JS in a HTML page opened with ",a("code",null,"file://"),".)"):[]))}this.linkIndex=0;var o=function(e){e.stopPropagation()},i=u(10,t.moduleResults).map(function(e){return r.renderResultsInModule(e)});return a("div",{id:"search",class:t.isVisible?"":"hidden"},a("div",{id:"search-form",onMouseDown:o},a("input",{placeholder:"Search in package by name",ref:function(e){r.input=e},onFocus:this.show.bind(this),onClick:this.show.bind(this),onInput:this.updateResults.bind(this)})),a("div",{id:"search-results",ref:function(e){r.searchResults=e},onMouseDown:o,onMouseOver:function(e){for(var t=e.target;t&&"function"==typeof t.getAttribute;){var n=t.getAttribute("data-link-index");if("string"==typeof n){var o=parseInt(n,10);r.setState({activeLinkIndex:o});break}t=t.parentNode}}},""===t.searchString?[a(f,null),a(d,null)]:0==i.length?a(v,{searchString:t.searchString}):a("ul",null,i)))},e.prototype.renderResultsInModule=function(e){var n=this,t=e.items,o=e.module,r=this.state.expanded[o]||t.length<=10,i=r?t:u(8,t);return a("li",{class:"search-module"},a("h4",null,o),a("ul",null,i.map(function(e){return t=e.item,a("li",{class:"search-result"},n.navigationLink(n.props.baseUrl+"/"+t.link,{},a(p,{html:t.display_html})));var t}),r?[]:a("li",{class:"more-results"},this.actionLink(function(){var e=Object.assign({},n.state.expanded);e[o]=!0,n.setState({expanded:e})},{},"show "+(t.length-i.length)+" more results from this module"))))},e.prototype.navigationLink=function(e,t){for(var n=this,o=[],r=2;r<arguments.length;r++)o[r-2]=arguments[r];var i=Object.assign({href:e,onClick:this.hide.bind(this)},t);return this.menuLink.apply(this,[i,function(){window.location.href=e,n.hide()}].concat(o))},e.prototype.actionLink=function(t,e){for(var n=[],o=2;o<arguments.length;o++)n[o-2]=arguments[o];var r=Object.assign({href:"#",onClick:function(e){e.preventDefault(),t()}},e);return this.menuLink.apply(this,[r,t].concat(n))},e.prototype.menuLink=function(e,t){for(var n=this,o=[],r=2;r<arguments.length;r++)o[r-2]=arguments[r];var i=this.linkIndex;i===this.state.activeLinkIndex&&(e.class=(e.class?e.class+" ":"")+"active-link",e.ref=function(e){e&&(n.activeLink=e)},this.activeLinkAction=t);var s=Object.assign({"data-link-index":i},e);return this.linkIndex+=1,a.apply(void 0,["a",s].concat(o))},e}(l),p=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return r(t,e),t.prototype.shouldComponentUpdate=function(e){return this.props.html!==e.html},t.prototype.render=function(e){return a("div",{dangerouslySetInnerHTML:{__html:e.html}})},t}(l);function d(){return a("table",{class:"keyboard-shortcuts"},a("tr",null,a("th",null,"Key"),a("th",null,"Shortcut")),a("tr",null,a("td",null,a("span",{class:"key"},"s")),a("td",null,"Open this search box")),a("tr",null,a("td",null,a("span",{class:"key"},"esc")),a("td",null,"Close this search box")),a("tr",null,a("td",null,a("span",{class:"key"},"↓"),",",a("span",{class:"key"},"ctrl")," + ",a("span",{class:"key"},"j")),a("td",null,"Move down in search results")),a("tr",null,a("td",null,a("span",{class:"key"},"↑"),",",a("span",{class:"key"},"ctrl")," + ",a("span",{class:"key"},"k")),a("td",null,"Move up in search results")),a("tr",null,a("td",null,a("span",{class:"key"},"↵")),a("td",null,"Go to active search result")))}function f(){return a("p",null,"You can find any exported type, constructor, class, function or pattern defined in this package by (approximate) name.")}function v(e){var t=[a("p",null,"Your search for '",e.searchString,"' produced the following list of results: ",a("code",null,"[]"),"."),a("p",null,a("code",null,"Nothing")," matches your query for '",e.searchString,"'."),a("p",null,a("code",null,"Left \"no matches for '",e.searchString,"'\" :: Either String (NonEmpty SearchResult)"))];return t[(e.searchString||"a").charCodeAt(0)%t.length]}function g(e,t){var n,o=document.getElementById("quick-jump-button");o&&s.render(a(h,{baseUrl:e||".",showHideTrigger:t||(n=o,function(e){var t=document.querySelector("#page-menu");s.render(a(c,{onClick:e,title:"Quick Jump"}),t,n)})}),document.body)}n.init=g,window.quickNav={init:g}},{"fuse.js":2,preact:3}],2:[function(e,t,n){var o,r;o=this,r=function(){return function(n){var o={};function r(e){if(o[e])return o[e].exports;var t=o[e]={i:e,l:!1,exports:{}};return n[e].call(t.exports,t,t.exports,r),t.l=!0,t.exports}return r.m=n,r.c=o,r.i=function(e){return e},r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:n})},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=8)}([function(e,t,n){"use strict";e.exports=function(e){return Array.isArray?Array.isArray(e):"[object Array]"===Object.prototype.toString.call(e)}},function(e,t,n){"use strict";var o=function(){function o(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(e,t,n){return t&&o(e.prototype,t),n&&o(e,n),e}}();var u=n(5),h=n(7),y=n(4),r=function(){function m(e,t){var n=t.location,o=void 0===n?0:n,r=t.distance,i=void 0===r?100:r,s=t.threshold,a=void 0===s?.6:s,l=t.maxPatternLength,c=void 0===l?32:l,u=t.isCaseSensitive,h=void 0!==u&&u,p=t.tokenSeparator,d=void 0===p?/ +/g:p,f=t.findAllMatches,v=void 0!==f&&f,g=t.minMatchCharLength,_=void 0===g?1:g;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,m),this.options={location:o,distance:i,threshold:a,maxPatternLength:c,isCaseSensitive:h,tokenSeparator:d,findAllMatches:v,minMatchCharLength:_},this.pattern=this.options.isCaseSensitive?e:e.toLowerCase(),this.pattern.length<=c&&(this.patternAlphabet=y(this.pattern))}return o(m,[{key:"search",value:function(e){if(this.options.isCaseSensitive||(e=e.toLowerCase()),this.pattern===e)return{isMatch:!0,score:0,matchedIndices:[[0,e.length-1]]};var t=this.options,n=t.maxPatternLength,o=t.tokenSeparator;if(this.pattern.length>n)return u(e,this.pattern,o);var r=this.options,i=r.location,s=r.distance,a=r.threshold,l=r.findAllMatches,c=r.minMatchCharLength;return h(e,this.pattern,this.patternAlphabet,{location:i,distance:s,threshold:a,findAllMatches:l,minMatchCharLength:c})}}]),m}();e.exports=r},function(e,t,n){"use strict";var u=n(0);e.exports=function(e,t){return function e(t,n,o){if(n){var r=n.indexOf("."),i=n,s=null;-1!==r&&(i=n.slice(0,r),s=n.slice(r+1));var a=t[i];if(null!=a)if(s||"string"!=typeof a&&"number"!=typeof a)if(u(a))for(var l=0,c=a.length;l<c;l+=1)e(a[l],s,o);else s&&e(a,s,o);else o.push(a.toString())}else o.push(t);return o}(e,t,[])}},function(e,t,n){"use strict";e.exports=function(){for(var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:[],t=1<arguments.length&&void 0!==arguments[1]?arguments[1]:1,n=[],o=-1,r=-1,i=0,s=e.length;i<s;i+=1){var a=e[i];a&&-1===o?o=i:a||-1===o||(t<=(r=i-1)-o+1&&n.push([o,r]),o=-1)}return e[i-1]&&t<=i-o&&n.push([o,i-1]),n}},function(e,t,n){"use strict";e.exports=function(e){for(var t={},n=e.length,o=0;o<n;o+=1)t[e.charAt(o)]=0;for(var r=0;r<n;r+=1)t[e.charAt(r)]|=1<<n-r-1;return t}},function(e,t,n){"use strict";var u=/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g;e.exports=function(e,t){var n=2<arguments.length&&void 0!==arguments[2]?arguments[2]:/ +/g,o=new RegExp(t.replace(u,"\\$&").replace(n,"|")),r=e.match(o),i=!!r,s=[];if(i)for(var a=0,l=r.length;a<l;a+=1){var c=r[a];s.push([e.indexOf(c),c.length-1])}return{score:i?.5:1,isMatch:i,matchedIndices:s}}},function(e,t,n){"use strict";e.exports=function(e,t){var n=t.errors,o=void 0===n?0:n,r=t.currentLocation,i=void 0===r?0:r,s=t.expectedLocation,a=void 0===s?0:s,l=t.distance,c=void 0===l?100:l,u=o/e.length,h=Math.abs(a-i);return c?u+h/c:h?1:u}},function(e,t,n){"use strict";var U=n(6),R=n(3);e.exports=function(e,t,n,o){for(var r=o.location,i=void 0===r?0:r,s=o.distance,a=void 0===s?100:s,l=o.threshold,c=void 0===l?.6:l,u=o.findAllMatches,h=void 0!==u&&u,p=o.minMatchCharLength,d=void 0===p?1:p,f=i,v=e.length,g=c,_=e.indexOf(t,f),m=t.length,y=[],k=0;k<v;k+=1)y[k]=0;if(-1!==_){var b=U(t,{errors:0,currentLocation:_,expectedLocation:f,distance:a});if(g=Math.min(b,g),-1!==(_=e.lastIndexOf(t,f+m))){var x=U(t,{errors:0,currentLocation:_,expectedLocation:f,distance:a});g=Math.min(x,g)}}_=-1;for(var S=[],w=1,L=m+v,C=1<<m-1,M=0;M<m;M+=1){for(var A=0,I=L;A<I;){U(t,{errors:M,currentLocation:f+I,expectedLocation:f,distance:a})<=g?A=I:L=I,I=Math.floor((L-A)/2+A)}L=I;var N=Math.max(1,f-I+1),T=h?v:Math.min(f+I,v)+m,O=Array(T+2);O[T+1]=(1<<M)-1;for(var P=T;N<=P;P-=1){var j=P-1,E=n[e.charAt(j)];if(E&&(y[j]=1),O[P]=(O[P+1]<<1|1)&E,0!==M&&(O[P]|=(S[P+1]|S[P])<<1|1|S[P+1]),O[P]&C&&(w=U(t,{errors:M,currentLocation:j,expectedLocation:f,distance:a}))<=g){if(g=w,(_=j)<=f)break;N=Math.max(1,2*f-_)}}if(g<U(t,{errors:M+1,currentLocation:f,expectedLocation:f,distance:a}))break;S=O}return{isMatch:0<=_,score:0===w?.001:w,matchedIndices:R(y,d)}}},function(e,t,n){"use strict";var o=function(){function o(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(e,t,n){return t&&o(e.prototype,t),n&&o(e,n),e}}();var i=n(1),F=n(2),U=n(0),r=function(){function D(e,t){var n=t.location,o=void 0===n?0:n,r=t.distance,i=void 0===r?100:r,s=t.threshold,a=void 0===s?.6:s,l=t.maxPatternLength,c=void 0===l?32:l,u=t.caseSensitive,h=void 0!==u&&u,p=t.tokenSeparator,d=void 0===p?/ +/g:p,f=t.findAllMatches,v=void 0!==f&&f,g=t.minMatchCharLength,_=void 0===g?1:g,m=t.id,y=void 0===m?null:m,k=t.keys,b=void 0===k?[]:k,x=t.shouldSort,S=void 0===x||x,w=t.getFn,L=void 0===w?F:w,C=t.sortFn,M=void 0===C?function(e,t){return e.score-t.score}:C,A=t.tokenize,I=void 0!==A&&A,N=t.matchAllTokens,T=void 0!==N&&N,O=t.includeMatches,P=void 0!==O&&O,j=t.includeScore,E=void 0!==j&&j,U=t.verbose,R=void 0!==U&&U;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,D),this.options={location:o,distance:i,threshold:a,maxPatternLength:c,isCaseSensitive:h,tokenSeparator:d,findAllMatches:v,minMatchCharLength:_,id:y,keys:b,includeMatches:P,includeScore:E,shouldSort:S,getFn:L,sortFn:M,verbose:R,tokenize:I,matchAllTokens:T},this.setCollection(e)}return o(D,[{key:"setCollection",value:function(e){return this.list=e}},{key:"search",value:function(e){this._log('---------\nSearch pattern: "'+e+'"');var t=this._prepareSearchers(e),n=t.tokenSearchers,o=t.fullSearcher,r=this._search(n,o),i=r.weights,s=r.results;return this._computeScore(i,s),this.options.shouldSort&&this._sort(s),this._format(s)}},{key:"_prepareSearchers",value:function(){var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:"",t=[];if(this.options.tokenize)for(var n=e.split(this.options.tokenSeparator),o=0,r=n.length;o<r;o+=1)t.push(new i(n[o],this.options));return{tokenSearchers:t,fullSearcher:new i(e,this.options)}}},{key:"_search",value:function(){var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:[],t=arguments[1],n=this.list,o={},r=[];if("string"==typeof n[0]){for(var i=0,s=n.length;i<s;i+=1)this._analyze({key:"",value:n[i],record:i,index:i},{resultMap:o,results:r,tokenSearchers:e,fullSearcher:t});return{weights:null,results:r}}for(var a={},l=0,c=n.length;l<c;l+=1)for(var u=n[l],h=0,p=this.options.keys.length;h<p;h+=1){var d=this.options.keys[h];if("string"!=typeof d){if(a[d.name]={weight:1-d.weight||1},d.weight<=0||1<d.weight)throw new Error("Key weight has to be > 0 and <= 1");d=d.name}else a[d]={weight:1};this._analyze({key:d,value:this.options.getFn(u,d),record:u,index:l},{resultMap:o,results:r,tokenSearchers:e,fullSearcher:t})}return{weights:a,results:r}}},{key:"_analyze",value:function(e,t){var n=e.key,o=e.arrayIndex,r=void 0===o?-1:o,i=e.value,s=e.record,a=e.index,l=t.tokenSearchers,c=void 0===l?[]:l,u=t.fullSearcher,h=void 0===u?[]:u,p=t.resultMap,d=void 0===p?{}:p,f=t.results,v=void 0===f?[]:f;if(null!=i){var g=!1,_=-1,m=0;if("string"==typeof i){this._log("\nKey: "+(""===n?"-":n));var y=h.search(i);if(this._log('Full text: "'+i+'", score: '+y.score),this.options.tokenize){for(var k=i.split(this.options.tokenSeparator),b=[],x=0;x<c.length;x+=1){var S=c[x];this._log('\nPattern: "'+S.pattern+'"');for(var w=!1,L=0;L<k.length;L+=1){var C=k[L],M=S.search(C),A={};M.isMatch?(A[C]=M.score,w=g=!0,b.push(M.score)):(A[C]=1,this.options.matchAllTokens||b.push(1)),this._log('Token: "'+C+'", score: '+A[C])}w&&(m+=1)}_=b[0];for(var I=b.length,N=1;N<I;N+=1)_+=b[N];_/=I,this._log("Token score average:",_)}var T=y.score;-1<_&&(T=(T+_)/2),this._log("Score average:",T);var O=!this.options.tokenize||!this.options.matchAllTokens||m>=c.length;if(this._log("\nCheck Matches: "+O),(g||y.isMatch)&&O){var P=d[a];P?P.output.push({key:n,arrayIndex:r,value:i,score:T,matchedIndices:y.matchedIndices}):(d[a]={item:s,output:[{key:n,arrayIndex:r,value:i,score:T,matchedIndices:y.matchedIndices}]},v.push(d[a]))}}else if(U(i))for(var j=0,E=i.length;j<E;j+=1)this._analyze({key:n,arrayIndex:j,value:i[j],record:s,index:a},{resultMap:d,results:v,tokenSearchers:c,fullSearcher:h})}}},{key:"_computeScore",value:function(e,t){this._log("\n\nComputing score:\n");for(var n=0,o=t.length;n<o;n+=1){for(var r=t[n].output,i=r.length,s=1,a=1,l=0;l<i;l+=1){var c=e?e[r[l].key].weight:1,u=(1===c?r[l].score:r[l].score||.001)*c;1!==c?a=Math.min(a,u):s*=r[l].nScore=u}t[n].score=1===a?s:a,this._log(t[n])}}},{key:"_sort",value:function(e){this._log("\n\nSorting...."),e.sort(this.options.sortFn)}},{key:"_format",value:function(e){var t=[];this.options.verbose&&this._log("\n\nOutput:\n\n",JSON.stringify(e));var n=[];this.options.includeMatches&&n.push(function(e,t){var n=e.output;t.matches=[];for(var o=0,r=n.length;o<r;o+=1){var i=n[o];if(0!==i.matchedIndices.length){var s={indices:i.matchedIndices,value:i.value};i.key&&(s.key=i.key),i.hasOwnProperty("arrayIndex")&&-1<i.arrayIndex&&(s.arrayIndex=i.arrayIndex),t.matches.push(s)}}}),this.options.includeScore&&n.push(function(e,t){t.score=e.score});for(var o=0,r=e.length;o<r;o+=1){var i=e[o];if(this.options.id&&(i.item=this.options.getFn(i.item,this.options.id)[0]),n.length){for(var s={item:i.item},a=0,l=n.length;a<l;a+=1)n[a](i,s);t.push(s)}else t.push(i.item)}return t}},{key:"_log",value:function(){var e;this.options.verbose&&(e=console).log.apply(e,arguments)}}]),D}();e.exports=r}])},"object"==typeof n&&"object"==typeof t?t.exports=r():"function"==typeof define&&define.amd?define("Fuse",[],r):"object"==typeof n?n.Fuse=r():o.Fuse=r()},{}],3:[function(e,m,t){!function(){"use strict";function n(e,t){var n,o,r,i,s=h;for(i=arguments.length;2<i--;)u.push(arguments[i]);for(t&&null!=t.children&&(u.length||u.push(t.children),delete t.children);u.length;)if((o=u.pop())&&void 0!==o.pop)for(i=o.length;i--;)u.push(o[i]);else"boolean"==typeof o&&(o=null),(r="function"!=typeof e)&&(null==o?o="":"number"==typeof o?o=String(o):"string"!=typeof o&&(r=!1)),r&&n?s[s.length-1]+=o:s===h?s=[o]:s.push(o),n=r;var a=new c;return a.nodeName=e,a.children=s,a.attributes=null==t?void 0:t,a.key=null==t?void 0:t.key,void 0!==R.vnode&&R.vnode(a),a}function C(e,t){for(var n in t)e[n]=t[n];return e}function i(e){!e.__d&&(e.__d=!0)&&1==d.push(e)&&(R.debounceRendering||r)(t)}function t(){var e,t=d;for(d=[];e=t.pop();)e.__d&&E(e)}function L(e,t){return e.__n===t||e.nodeName.toLowerCase()===t.toLowerCase()}function M(e){var t=C({},e.attributes);t.children=e.children;var n=e.nodeName.defaultProps;if(void 0!==n)for(var o in n)void 0===t[o]&&(t[o]=n[o]);return t}function A(e){var t=e.parentNode;t&&t.removeChild(e)}function v(e,t,n,o,r){if("className"===t&&(t="class"),"key"===t);else if("ref"===t)n&&n(null),o&&o(e);else if("class"!==t||r)if("style"===t){if(o&&"string"!=typeof o&&"string"!=typeof n||(e.style.cssText=o||""),o&&"object"==typeof o){if("string"!=typeof n)for(var i in n)i in o||(e.style[i]="");for(var i in o)e.style[i]="number"==typeof o[i]&&!1===p.test(i)?o[i]+"px":o[i]}}else if("dangerouslySetInnerHTML"===t)o&&(e.innerHTML=o.__html||"");else if("o"==t[0]&&"n"==t[1]){var s=t!==(t=t.replace(/Capture$/,""));t=t.toLowerCase().substring(2),o?n||e.addEventListener(t,l,s):e.removeEventListener(t,l,s),(e.__l||(e.__l={}))[t]=o}else if("list"!==t&&"type"!==t&&!r&&t in e){try{e[t]=null==o?"":o}catch(e){}null!=o&&!1!==o||"spellcheck"==t||e.removeAttribute(t)}else{var a=r&&t!==(t=t.replace(/^xlink:?/,""));null==o||!1===o?a?e.removeAttributeNS("http://www.w3.org/1999/xlink",t.toLowerCase()):e.removeAttribute(t):"function"!=typeof o&&(a?e.setAttributeNS("http://www.w3.org/1999/xlink",t.toLowerCase(),o):e.setAttribute(t,o))}else e.className=o||""}function l(e){return this.__l[e.type](R.event&&R.event(e)||e)}function I(){for(var e;e=D.pop();)R.afterMount&&R.afterMount(e),e.componentDidMount&&e.componentDidMount()}function N(e,t,n,o,r,i){F++||(g=null!=r&&void 0!==r.ownerSVGElement,_=null!=e&&!("__preactattr_"in e));var s=T(e,t,n,o,i);return r&&s.parentNode!==r&&r.appendChild(s),--F||(_=!1,i||I()),s}function T(e,t,n,o,r){var i=e,s=g;if(null!=t&&"boolean"!=typeof t||(t=""),"string"==typeof t||"number"==typeof t)return e&&void 0!==e.splitText&&e.parentNode&&(!e._component||r)?e.nodeValue!=t&&(e.nodeValue=t):(i=document.createTextNode(t),e&&(e.parentNode&&e.parentNode.replaceChild(i,e),O(e,!0))),i.__preactattr_=!0,i;var a,l,c=t.nodeName;if("function"==typeof c)return function(e,t,n,o){var r=e&&e._component,i=r,s=e,a=r&&e._componentConstructor===t.nodeName,l=a,c=M(t);for(;r&&!l&&(r=r.__u);)l=r.constructor===t.nodeName;r&&l&&(!o||r._component)?(j(r,c,3,n,o),e=r.base):(i&&!a&&(U(i),e=s=null),r=P(t.nodeName,c,n),e&&!r.__b&&(r.__b=e,s=null),j(r,c,1,n,o),e=r.base,s&&e!==s&&(s._component=null,O(s,!1)));return e}(e,t,n,o);if(g="svg"===c||"foreignObject"!==c&&g,c=String(c),(!e||!L(e,c))&&(a=c,(l=g?document.createElementNS("http://www.w3.org/2000/svg",a):document.createElement(a)).__n=a,i=l,e)){for(;e.firstChild;)i.appendChild(e.firstChild);e.parentNode&&e.parentNode.replaceChild(i,e),O(e,!0)}var u=i.firstChild,h=i.__preactattr_,p=t.children;if(null==h){h=i.__preactattr_={};for(var d=i.attributes,f=d.length;f--;)h[d[f].name]=d[f].value}return!_&&p&&1===p.length&&"string"==typeof p[0]&&null!=u&&void 0!==u.splitText&&null==u.nextSibling?u.nodeValue!=p[0]&&(u.nodeValue=p[0]):(p&&p.length||null!=u)&&function(e,t,n,o,r){var i,s,a,l,c,u=e.childNodes,h=[],p={},d=0,f=0,v=u.length,g=0,_=t?t.length:0;if(0!==v)for(var m=0;m<v;m++){var y=u[m],k=y.__preactattr_,b=_&&k?y._component?y._component.__k:k.key:null;null!=b?(d++,p[b]=y):(k||(void 0!==y.splitText?!r||y.nodeValue.trim():r))&&(h[g++]=y)}if(0!==_)for(var m=0;m<_;m++){l=t[m],c=null;var b=l.key;if(null!=b)d&&void 0!==p[b]&&(c=p[b],p[b]=void 0,d--);else if(f<g)for(i=f;i<g;i++)if(void 0!==h[i]&&(x=s=h[i],w=r,"string"==typeof(S=l)||"number"==typeof S?void 0!==x.splitText:"string"==typeof S.nodeName?!x._componentConstructor&&L(x,S.nodeName):w||x._componentConstructor===S.nodeName)){c=s,h[i]=void 0,i===g-1&&g--,i===f&&f++;break}c=T(c,l,n,o),a=u[m],c&&c!==e&&c!==a&&(null==a?e.appendChild(c):c===a.nextSibling?A(a):e.insertBefore(c,a))}var x,S,w;if(d)for(var m in p)void 0!==p[m]&&O(p[m],!1);for(;f<=g;)void 0!==(c=h[g--])&&O(c,!1)}(i,p,n,o,_||null!=h.dangerouslySetInnerHTML),function(e,t,n){var o;for(o in n)t&&null!=t[o]||null==n[o]||v(e,o,n[o],n[o]=void 0,g);for(o in t)"children"===o||"innerHTML"===o||o in n&&t[o]===("value"===o||"checked"===o?e[o]:n[o])||v(e,o,n[o],n[o]=t[o],g)}(i,t.attributes,h),g=s,i}function O(e,t){var n=e._component;n?U(n):(null!=e.__preactattr_&&e.__preactattr_.ref&&e.__preactattr_.ref(null),!1!==t&&null!=e.__preactattr_||A(e),o(e))}function o(e){for(e=e.lastChild;e;){var t=e.previousSibling;O(e,!0),e=t}}function P(e,t,n){var o,r=f.length;for(e.prototype&&e.prototype.render?(o=new e(t,n),a.call(o,t,n)):((o=new a(t,n)).constructor=e,o.render=s);r--;)if(f[r].constructor===e)return o.__b=f[r].__b,f.splice(r,1),o;return o}function s(e,t,n){return this.constructor(e,n)}function j(e,t,n,o,r){e.__x||(e.__x=!0,e.__r=t.ref,e.__k=t.key,delete t.ref,delete t.key,void 0===e.constructor.getDerivedStateFromProps&&(!e.base||r?e.componentWillMount&&e.componentWillMount():e.componentWillReceiveProps&&e.componentWillReceiveProps(t,o)),o&&o!==e.context&&(e.__c||(e.__c=e.context),e.context=o),e.__p||(e.__p=e.props),e.props=t,e.__x=!1,0!==n&&(1!==n&&!1===R.syncComponentUpdates&&e.base?i(e):E(e,1,r)),e.__r&&e.__r(e))}function E(e,t,n,o){if(!e.__x){var r,i,s,a=e.props,l=e.state,c=e.context,u=e.__p||a,h=e.__s||l,p=e.__c||c,d=e.base,f=e.__b,v=d||f,g=e._component,_=!1,m=p;if(e.constructor.getDerivedStateFromProps&&(l=C(C({},l),e.constructor.getDerivedStateFromProps(a,l)),e.state=l),d&&(e.props=u,e.state=h,e.context=p,2!==t&&e.shouldComponentUpdate&&!1===e.shouldComponentUpdate(a,l,c)?_=!0:e.componentWillUpdate&&e.componentWillUpdate(a,l,c),e.props=a,e.state=l,e.context=c),e.__p=e.__s=e.__c=e.__b=null,e.__d=!1,!_){r=e.render(a,l,c),e.getChildContext&&(c=C(C({},c),e.getChildContext())),d&&e.getSnapshotBeforeUpdate&&(m=e.getSnapshotBeforeUpdate(u,h));var y,k,b=r&&r.nodeName;if("function"==typeof b){var x=M(r);(i=g)&&i.constructor===b&&x.key==i.__k?j(i,x,1,c,!1):(y=i,e._component=i=P(b,x,c),i.__b=i.__b||f,i.__u=e,j(i,x,0,c,!1),E(i,1,n,!0)),k=i.base}else s=v,(y=g)&&(s=e._component=null),(v||1===t)&&(s&&(s._component=null),k=N(s,r,c,n||!d,v&&v.parentNode,!0));if(v&&k!==v&&i!==g){var S=v.parentNode;S&&k!==S&&(S.replaceChild(k,v),y||(v._component=null,O(v,!1)))}if(y&&U(y),(e.base=k)&&!o){for(var w=e,L=e;L=L.__u;)(w=L).base=k;k._component=w,k._componentConstructor=w.constructor}}for(!d||n?D.unshift(e):_||(e.componentDidUpdate&&e.componentDidUpdate(u,h,m),R.afterUpdate&&R.afterUpdate(e));e.__h.length;)e.__h.pop().call(e);F||o||I()}}function U(e){R.beforeUnmount&&R.beforeUnmount(e);var t=e.base;e.__x=!0,e.componentWillUnmount&&e.componentWillUnmount(),e.base=null;var n=e._component;n?U(n):t&&(t.__preactattr_&&t.__preactattr_.ref&&t.__preactattr_.ref(null),A(e.__b=t),f.push(e),o(t)),e.__r&&e.__r(null)}function a(e,t){this.__d=!0,this.context=t,this.props=e,this.state=this.state||{},this.__h=[]}var c=function(){},R={},u=[],h=[],r="function"==typeof Promise?Promise.resolve().then.bind(Promise.resolve()):setTimeout,p=/acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i,d=[],D=[],F=0,g=!1,_=!1,f=[];C(a.prototype,{setState:function(e,t){this.__s||(this.__s=this.state),this.state=C(C({},this.state),"function"==typeof e?e(this.state,this.props):e),t&&this.__h.push(t),i(this)},forceUpdate:function(e){e&&this.__h.push(e),E(this,2)},render:function(){}});var e={h:n,createElement:n,cloneElement:function(e,t){return n(e.nodeName,C(C({},e.attributes),t),2<arguments.length?[].slice.call(arguments,2):e.children)},Component:a,render:function(e,t,n){return N(n,e,{},!1,t,!1)},rerender:t,options:R};void 0!==m?m.exports=e:self.preact=e}()},{}]},{},[1]);
 //# sourceMappingURL=quick-jump.min.js.map
diff --git a/src/Documentation/Haddock.hs b/src/Documentation/Haddock.hs
--- a/src/Documentation/Haddock.hs
+++ b/src/Documentation/Haddock.hs
@@ -8,7 +8,7 @@
 -- Stability   :  experimental
 -- Portability :  portable
 --
--- The Haddock API: A rudimentory, highly experimental API exposing some of
+-- The Haddock API: A rudimentary, highly experimental API exposing some of
 -- the internals of Haddock. Don't expect it to be stable.
 -----------------------------------------------------------------------------
 module Documentation.Haddock (
@@ -52,9 +52,7 @@
   -- * Interface files
   InterfaceFile(..),
   readInterfaceFile,
-  nameCacheFromGhc,
   freshNameCache,
-  NameCacheAccessor,
 
   -- * Flags and options
   Flag(..),
diff --git a/src/Haddock.hs b/src/Haddock.hs
--- a/src/Haddock.hs
+++ b/src/Haddock.hs
@@ -1,6 +1,11 @@
-{-# OPTIONS_GHC -Wwarn #-}
-{-# LANGUAGE CPP, ScopedTypeVariables, OverloadedStrings, Rank2Types #-}
-{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE LambdaCase          #-}
+{-# LANGUAGE NamedFieldPuns      #-}
+{-# LANGUAGE OverloadedStrings   #-}
+{-# LANGUAGE Rank2Types          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TupleSections       #-}
+{-# OPTIONS_GHC -Wwarn           #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Haddock
@@ -46,7 +51,7 @@
 import Data.Bifunctor (second)
 import Data.Foldable (forM_, foldl')
 import Data.Traversable (for)
-import Data.List (isPrefixOf)
+import Data.List (find, isPrefixOf, nub)
 import Control.Exception
 import Data.Maybe
 import Data.IORef
@@ -69,8 +74,11 @@
 import GHC hiding (verbosity)
 import GHC.Settings.Config
 import GHC.Driver.Session hiding (projectVersion, verbosity)
+import GHC.Driver.Config.Logger (initLogFlags)
 import GHC.Driver.Env
 import GHC.Utils.Error
+import GHC.Utils.Logger
+import GHC.Types.Name.Cache
 import GHC.Unit
 import GHC.Utils.Panic (handleGhcException)
 import GHC.Data.FastString
@@ -188,17 +196,24 @@
     unit_state <- hsc_units <$> getSession
 
     forM_ (optShowInterfaceFile flags) $ \path -> liftIO $ do
-      mIfaceFile <- readInterfaceFiles freshNameCache [(("", Nothing), path)] noChecks
-      forM_ mIfaceFile $ \(_, ifaceFile) -> do
-        putMsg logger dflags $ renderJson (jsonInterfaceFile ifaceFile)
+      name_cache <- freshNameCache
+      mIfaceFile <- readInterfaceFiles name_cache [(("", Nothing), Visible, path)] noChecks
+      forM_ mIfaceFile $ \(_,_,_, ifaceFile) -> do
+        putMsg logger $ renderJson (jsonInterfaceFile ifaceFile)
 
     if not (null files) then do
       (packages, ifaces, homeLinks) <- readPackagesAndProcessModules flags files
+      let packageInfo = PackageInfo { piPackageName =
+                                        fromMaybe (PackageName mempty) (optPackageName flags)
+                                    , piPackageVersion =
+                                        fromMaybe (makeVersion []) (optPackageVersion flags)
+                                    }
 
       -- Dump an "interface file" (.haddock file), if requested.
       forM_ (optDumpInterfaceFile flags) $ \path -> liftIO $ do
         writeInterfaceFile path InterfaceFile {
             ifInstalledIfaces = map toInstalledIface ifaces
+          , ifPackageInfo     = packageInfo
           , ifLinkEnv         = homeLinks
           }
 
@@ -210,7 +225,8 @@
         throwE "No input file(s)."
 
       -- Get packages supplied with --read-interface.
-      packages <- liftIO $ readInterfaceFiles freshNameCache (readIfaceArgs flags) noChecks
+      name_cache <- liftIO $ freshNameCache
+      packages <- liftIO $ readInterfaceFiles name_cache (readIfaceArgs flags) noChecks
 
       -- Render even though there are no input files (usually contents/index).
       liftIO $ renderStep logger dflags unit_state flags sinceQual qual packages []
@@ -249,42 +265,64 @@
 
 
 readPackagesAndProcessModules :: [Flag] -> [String]
-                              -> Ghc ([(DocPaths, InterfaceFile)], [Interface], LinkEnv)
+                              -> Ghc ([(DocPaths, Visibility, FilePath, InterfaceFile)], [Interface], LinkEnv)
 readPackagesAndProcessModules flags files = do
     -- Get packages supplied with --read-interface.
     let noChecks = Flag_BypassInterfaceVersonCheck `elem` flags
-    packages <- readInterfaceFiles nameCacheFromGhc (readIfaceArgs flags) noChecks
+    name_cache <- hsc_NC <$> getSession
+    packages <- liftIO $ readInterfaceFiles name_cache (readIfaceArgs flags) noChecks
 
     -- Create the interfaces -- this is the core part of Haddock.
-    let ifaceFiles = map snd packages
+    let ifaceFiles = map (\(_, _, _, ifaceFile) -> ifaceFile) packages
     (ifaces, homeLinks) <- processModules (verbosity flags) files flags ifaceFiles
 
     return (packages, ifaces, homeLinks)
 
 
 renderStep :: Logger -> DynFlags -> UnitState -> [Flag] -> SinceQual -> QualOption
-           -> [(DocPaths, InterfaceFile)] -> [Interface] -> IO ()
+           -> [(DocPaths, Visibility, FilePath, InterfaceFile)] -> [Interface] -> IO ()
 renderStep logger dflags unit_state flags sinceQual nameQual pkgs interfaces = do
-  updateHTMLXRefs pkgs
+  updateHTMLXRefs (map (\(docPath, _ifaceFilePath, _showModules, ifaceFile) ->
+                          ( case baseUrl flags of
+                              Nothing  -> fst docPath
+                              Just url -> url </> packageName (ifUnitId ifaceFile)
+                          , ifaceFile)) pkgs)
   let
-    ifaceFiles = map snd pkgs
-    installedIfaces = concatMap ifInstalledIfaces ifaceFiles
+    installedIfaces =
+      map
+        (\(_, showModules, ifaceFilePath, ifaceFile)
+          -> (ifaceFilePath, mkPackageInterfaces showModules ifaceFile))
+        pkgs
     extSrcMap = Map.fromList $ do
-      ((_, Just path), ifile) <- pkgs
+      ((_, Just path), _, _, ifile) <- pkgs
       iface <- ifInstalledIfaces ifile
       return (instMod iface, path)
   render logger dflags unit_state flags sinceQual nameQual interfaces installedIfaces extSrcMap
+  where
+    -- get package name from unit-id
+    packageName :: Unit -> String
+    packageName unit =
+      case lookupUnit unit_state unit of
+        Nothing  -> show unit
+        Just pkg -> unitPackageNameString pkg
 
 -- | Render the interfaces with whatever backend is specified in the flags.
 render :: Logger -> DynFlags -> UnitState -> [Flag] -> SinceQual -> QualOption -> [Interface]
-       -> [InstalledInterface] -> Map Module FilePath -> IO ()
-render logger dflags unit_state flags sinceQual qual ifaces installedIfaces extSrcMap = do
+       -> [(FilePath, PackageInterfaces)] -> Map Module FilePath -> IO ()
+render log' dflags unit_state flags sinceQual qual ifaces packages extSrcMap = do
 
   let
+    packageInfo = PackageInfo { piPackageName    = fromMaybe (PackageName mempty)
+                                                 $ optPackageName flags
+                              , piPackageVersion = fromMaybe (makeVersion [])
+                                                 $ optPackageVersion flags
+                              }
+
     title                = fromMaybe "" (optTitle flags)
     unicode              = Flag_UseUnicode `elem` flags
     pretty               = Flag_PrettyHtml `elem` flags
     opt_wiki_urls        = wikiUrls          flags
+    opt_base_url         = baseUrl           flags
     opt_contents_url     = optContentsUrl    flags
     opt_index_url        = optIndexUrl       flags
     odir                 = outputDir         flags
@@ -294,13 +332,37 @@
     dflags'
       | unicode          = gopt_set dflags Opt_PrintUnicodeSyntax
       | otherwise        = dflags
+    logger               = setLogFlags log' (initLogFlags dflags')
 
     visibleIfaces    = [ i | i <- ifaces, OptHide `notElem` ifaceOptions i ]
 
-    -- /All/ visible interfaces including external package modules.
-    allIfaces        = map toInstalledIface ifaces ++ installedIfaces
-    allVisibleIfaces = [ i | i <- allIfaces, OptHide `notElem` instOptions i ]
+    -- /All/ interfaces including external package modules, grouped by
+    -- interface file (package).
+    allPackages      :: [PackageInterfaces]
+    allPackages      = [PackageInterfaces
+                         { piPackageInfo = packageInfo
+                         , piVisibility  = Visible
+                         , piInstalledInterfaces  = map toInstalledIface ifaces
+                         }]
+                    ++ map snd packages
 
+    -- /All/ visible interfaces including external package modules, grouped by
+    -- interface file (package).
+    allVisiblePackages :: [PackageInterfaces]
+    allVisiblePackages = [ pinfo { piInstalledInterfaces =
+                                     filter (\i -> OptHide `notElem` instOptions i)
+                                            piInstalledInterfaces
+                                 }
+                         | pinfo@PackageInterfaces
+                             { piVisibility = Visible
+                             , piInstalledInterfaces
+                             } <- allPackages
+                         ]
+
+    -- /All/ installed interfaces.
+    allInstalledIfaces :: [InstalledInterface]
+    allInstalledIfaces = concatMap (piInstalledInterfaces . snd) packages
+
     pkgMod           = fmap ifaceMod (listToMaybe ifaces)
     pkgKey           = fmap moduleUnit pkgMod
     pkgStr           = fmap unitString pkgKey
@@ -343,7 +405,7 @@
     sourceUrls' = (srcBase, srcModule', pkgSrcMap', pkgSrcLMap')
 
     installedMap :: Map Module InstalledInterface
-    installedMap = Map.fromList [ (unwire (instMod iface), iface) | iface <- installedIfaces ]
+    installedMap = Map.fromList [ (unwire (instMod iface), iface) | iface <- allInstalledIfaces ]
 
     -- The user gives use base-4.9.0.0, but the InstalledInterface
     -- records the *wired in* identity base.  So untranslate it
@@ -366,38 +428,58 @@
   themes   <- getThemes libDir flags >>= either bye return
 
   let withQuickjump = Flag_QuickJumpIndex `elem` flags
+      withBaseURL = isJust
+                  . find (\flag -> case flag of
+                           Flag_BaseURL base_url ->
+                             base_url /= "." && base_url /= "./"
+                           _ -> False
+                         )
+                  $ flags
 
   when (Flag_GenIndex `elem` flags) $ do
-    withTiming logger dflags' "ppHtmlIndex" (const ()) $ do
+    withTiming logger "ppHtmlIndex" (const ()) $ do
       _ <- {-# SCC ppHtmlIndex #-}
            ppHtmlIndex odir title pkgStr
                   themes opt_mathjax opt_contents_url sourceUrls' opt_wiki_urls
-                  allVisibleIfaces pretty
+                  withQuickjump
+                  (concatMap piInstalledInterfaces allVisiblePackages) pretty
       return ()
 
-    copyHtmlBits odir libDir themes withQuickjump
+    unless withBaseURL $
+      copyHtmlBits odir libDir themes withQuickjump
 
   when (Flag_GenContents `elem` flags) $ do
-    withTiming logger dflags' "ppHtmlContents" (const ()) $ do
+    withTiming logger "ppHtmlContents" (const ()) $ do
       _ <- {-# SCC ppHtmlContents #-}
            ppHtmlContents unit_state odir title pkgStr
                      themes opt_mathjax opt_index_url sourceUrls' opt_wiki_urls
-                     allVisibleIfaces True prologue pretty
+                     withQuickjump
+                     allVisiblePackages True prologue pretty
                      sincePkg (makeContentsQual qual)
       return ()
     copyHtmlBits odir libDir themes withQuickjump
 
+  when withQuickjump $ void $
+            ppJsonIndex odir sourceUrls' opt_wiki_urls
+                        unicode Nothing qual
+                        ifaces
+                        ( nub
+                        . map fst
+                        . filter ((== Visible) . piVisibility . snd)
+                        $ packages)
+
   when (Flag_Html `elem` flags) $ do
-    withTiming logger dflags' "ppHtml" (const ()) $ do
+    withTiming logger "ppHtml" (const ()) $ do
       _ <- {-# SCC ppHtml #-}
            ppHtml unit_state title pkgStr visibleIfaces reexportedIfaces odir
                   prologue
-                  themes opt_mathjax sourceUrls' opt_wiki_urls
-                  opt_contents_url opt_index_url unicode sincePkg qual
-                  pretty withQuickjump
+                  themes opt_mathjax sourceUrls' opt_wiki_urls opt_base_url
+                  opt_contents_url opt_index_url unicode sincePkg packageInfo
+                  qual pretty withQuickjump
       return ()
-    copyHtmlBits odir libDir themes withQuickjump
-    writeHaddockMeta odir withQuickjump
+    unless withBaseURL $ do
+      copyHtmlBits odir libDir themes withQuickjump
+      writeHaddockMeta odir withQuickjump
 
   -- TODO: we throw away Meta for both Hoogle and LaTeX right now,
   -- might want to fix that if/when these two get some work on them
@@ -423,14 +505,14 @@
           ]
 
   when (Flag_LaTeX `elem` flags) $ do
-    withTiming logger dflags' "ppLatex" (const ()) $ do
+    withTiming logger "ppLatex" (const ()) $ do
       _ <- {-# SCC ppLatex #-}
            ppLaTeX title pkgStr visibleIfaces odir (fmap _doc prologue) opt_latex_style
                    libDir
       return ()
 
   when (Flag_HyperlinkedSource `elem` flags && not (null ifaces)) $ do
-    withTiming logger dflags' "ppHyperlinkedSource" (const ()) $ do
+    withTiming logger "ppHyperlinkedSource" (const ()) $ do
       _ <- {-# SCC ppHyperlinkedSource #-}
            ppHyperlinkedSource (verbosity flags) odir libDir opt_source_css pretty srcMap ifaces
       return ()
@@ -441,23 +523,22 @@
 -------------------------------------------------------------------------------
 
 
-readInterfaceFiles :: MonadIO m
-                   => NameCacheAccessor m
-                   -> [(DocPaths, FilePath)]
+readInterfaceFiles :: NameCache
+                   -> [(DocPaths, Visibility, FilePath)]
                    -> Bool
-                   -> m [(DocPaths, InterfaceFile)]
+                   -> IO [(DocPaths, Visibility, FilePath, InterfaceFile)]
 readInterfaceFiles name_cache_accessor pairs bypass_version_check = do
   catMaybes `liftM` mapM ({-# SCC readInterfaceFile #-} tryReadIface) pairs
   where
     -- try to read an interface, warn if we can't
-    tryReadIface (paths, file) =
+    tryReadIface (paths, vis, file) =
       readInterfaceFile name_cache_accessor file bypass_version_check >>= \case
-        Left err -> liftIO $ do
+        Left err -> do
           putStrLn ("Warning: Cannot read " ++ file ++ ":")
           putStrLn ("   " ++ err)
           putStrLn "Skipping this interface."
           return Nothing
-        Right f -> return $ Just (paths, f)
+        Right f -> return (Just (paths, vis, file, f))
 
 
 -------------------------------------------------------------------------------
@@ -678,12 +759,12 @@
     isSourceCssFlag _ = False
 
 
-updateHTMLXRefs :: [(DocPaths, InterfaceFile)] -> IO ()
+updateHTMLXRefs :: [(FilePath, InterfaceFile)] -> IO ()
 updateHTMLXRefs packages = do
   writeIORef html_xrefs_ref (Map.fromList mapping)
   writeIORef html_xrefs_ref' (Map.fromList mapping')
   where
-    mapping = [ (instMod iface, html) | ((html, _), ifaces) <- packages
+    mapping = [ (instMod iface, html) | (html, ifaces) <- packages
               , iface <- ifInstalledIfaces ifaces ]
     mapping' = [ (moduleName m, html) | (m, html) <- mapping ]
 
diff --git a/src/Haddock/Backends/Hoogle.hs b/src/Haddock/Backends/Hoogle.hs
--- a/src/Haddock/Backends/Hoogle.hs
+++ b/src/Haddock/Backends/Hoogle.hs
@@ -31,7 +31,6 @@
 import GHC.Driver.Ppr
 import GHC.Utils.Outputable as Outputable
 import GHC.Utils.Panic
-import GHC.Parser.Annotation (IsUnicodeSyntax(..))
 import GHC.Unit.State
 
 import Data.Char
@@ -88,7 +87,7 @@
         drop_ty (HsFunTy x w a b) = HsFunTy x w (drop_lty a) (drop_lty b)
         drop_ty (HsListTy x a) = HsListTy x (drop_lty a)
         drop_ty (HsTupleTy x a b) = HsTupleTy x a (map drop_lty b)
-        drop_ty (HsOpTy x a b c) = HsOpTy x (drop_lty a) b (drop_lty c)
+        drop_ty (HsOpTy x p a b c) = HsOpTy x p (drop_lty a) b (drop_lty c)
         drop_ty (HsParTy x a) = HsParTy x (drop_lty a)
         drop_ty (HsKindSig x a b) = HsKindSig x (drop_lty a) b
         drop_ty (HsDocTy _ a _) = drop_ty $ unL a
@@ -247,11 +246,11 @@
         f (PrefixCon _ args) = [typeSig name $ (map hsScaledThing args) ++ [resType]]
         f (InfixCon a1 a2) = f $ PrefixCon [] [a1,a2]
         f (RecCon (L _ recs)) = f (PrefixCon [] $ map (hsLinear . cd_fld_type . unLoc) recs) ++ concat
-                          [(concatMap (lookupCon dflags subdocs . noLocA . extFieldOcc . unLoc) (cd_fld_names r)) ++
-                           [out dflags (map (extFieldOcc . unLoc) $ cd_fld_names r) `typeSig` [resType, cd_fld_type r]]
+                          [(concatMap (lookupCon dflags subdocs . noLocA . foExt . unLoc) (cd_fld_names r)) ++
+                           [out dflags (map (foExt . unLoc) $ cd_fld_names r) `typeSig` [resType, cd_fld_type r]]
                           | r <- map unLoc recs]
 
-        funs = foldr1 (\x y -> reL $ HsFunTy noAnn (HsUnrestrictedArrow NormalSyntax) x y)
+        funs = foldr1 (\x y -> reL $ HsFunTy noAnn (HsUnrestrictedArrow noHsUniTok) x y)
         apps = foldl1 (\x y -> reL $ HsAppTy noExtField x y)
 
         typeSig nm flds = operator nm ++ " :: " ++
@@ -280,12 +279,12 @@
         name = out dflags $ map unL names
         con_sig_ty = HsSig noExtField outer_bndrs theta_ty where
           theta_ty = case mcxt of
-            Just theta -> noLocA (HsQualTy { hst_xqual = noExtField, hst_ctxt = Just theta, hst_body = tau_ty })
+            Just theta -> noLocA (HsQualTy { hst_xqual = noExtField, hst_ctxt = theta, hst_body = tau_ty })
             Nothing -> tau_ty
           tau_ty = foldr mkFunTy res_ty $
             case args of PrefixConGADT pos_args -> map hsScaledThing pos_args
-                         RecConGADT (L _ flds) -> map (cd_fld_type . unL) flds
-          mkFunTy a b = noLocA (HsFunTy noAnn (HsUnrestrictedArrow NormalSyntax) a b)
+                         RecConGADT (L _ flds) _ -> map (cd_fld_type . unL) flds
+          mkFunTy a b = noLocA (HsFunTy noAnn (HsUnrestrictedArrow noHsUniTok) a b)
 
 ppFixity :: DynFlags -> (Name, Fixity) -> [String]
 ppFixity dflags (name, fixity) = [out dflags ((FixitySig noExtField [noLocA name] fixity) :: FixitySig GhcRn)]
@@ -354,7 +353,7 @@
   markupMathInline           = const $ str "<math>",
   markupMathDisplay          = const $ str "<math>",
   markupUnorderedList        = box (TagL 'u'),
-  markupOrderedList          = box (TagL 'o'),
+  markupOrderedList          = box (TagL 'o') . map snd,
   markupDefList              = box (TagL 'u') . map (\(a,b) -> TagInline "i" a : Str " " : b),
   markupCodeBlock            = box TagPre,
   markupHyperlink            = \(Hyperlink url mLabel) -> box (TagInline "a") (fromMaybe (str url) mLabel),
diff --git a/src/Haddock/Backends/Hyperlinker.hs b/src/Haddock/Backends/Hyperlinker.hs
--- a/src/Haddock/Backends/Hyperlinker.hs
+++ b/src/Haddock/Backends/Hyperlinker.hs
@@ -9,6 +9,7 @@
 
 import Haddock.Types
 import Haddock.Utils (writeUtf8File, out, verbose, Verbosity)
+import Haddock.InterfaceFile
 import Haddock.Backends.Hyperlinker.Renderer
 import Haddock.Backends.Hyperlinker.Parser
 import Haddock.Backends.Hyperlinker.Types
@@ -20,13 +21,11 @@
 import System.FilePath
 
 import GHC.Iface.Ext.Types  ( pattern HiePath, HieFile(..), HieASTs(..), HieAST(..), SourcedNodeInfo(..) )
-import GHC.Iface.Ext.Binary ( readHieFile, hie_file_result, NameCacheUpdater(..))
-import GHC.Types.SrcLoc     ( realSrcLocSpan, mkRealSrcLoc )
+import GHC.Iface.Ext.Binary ( readHieFile, hie_file_result )
+import GHC.Types.SrcLoc     ( realSrcLocSpan, mkRealSrcLoc, srcSpanFile )
 import Data.Map as M
 import GHC.Data.FastString     ( mkFastString )
 import GHC.Unit.Module         ( Module, moduleName )
-import GHC.Types.Name.Cache    ( initNameCache )
-import GHC.Types.Unique.Supply ( mkSplitUniqSupply )
 
 
 -- | Generate hyperlinked source for given interfaces.
@@ -58,21 +57,19 @@
 ppHyperlinkedModuleSource verbosity srcdir pretty srcs iface = case ifaceHieFile iface of
     Just hfp -> do
         -- Parse the GHC-produced HIE file
-        u <- mkSplitUniqSupply 'a'
-        let nc = (initNameCache u [])
-            ncu = NCU $ \f -> pure $ snd $ f nc
+        nc <- freshNameCache
         HieFile { hie_hs_file = file
                 , hie_asts = HieASTs asts
                 , hie_types = types
                 , hie_hs_src = rawSrc
                 } <- hie_file_result
-                 <$> (readHieFile ncu hfp)
+                 <$> (readHieFile nc hfp)
 
         -- Get the AST and tokens corresponding to the source file we want
         let fileFs = mkFastString file
             mast | M.size asts == 1 = snd <$> M.lookupMin asts
                  | otherwise        = M.lookup (HiePath (mkFastString file)) asts
-            tokens = parse df file rawSrc
+            tokens' = parse df file rawSrc
             ast = fromMaybe (emptyHieAst fileFs) mast
             fullAst = recoverFullIfaceTypes df types ast
 
@@ -82,6 +79,14 @@
           else out verbosity verbose $ unwords [ "couldn't find ast for"
                                                , file, show (M.keys asts) ]
 
+        -- The C preprocessor can double the backslashes on tokens (see #19236),
+        -- which means the source spans will not be comparable and we will not
+        -- be able to associate the HieAST with the correct tokens.
+        --
+        -- We work around this by setting the source span of the tokens to the file
+        -- name from the HieAST
+        let tokens = fmap (\tk -> tk {tkSpan = (tkSpan tk){srcSpanFile = srcSpanFile $ nodeSpan fullAst}}) tokens'
+
         -- Produce and write out the hyperlinked sources
         writeUtf8File path . renderToString pretty . render' fullAst $ tokens
     Nothing -> return ()
@@ -107,4 +112,3 @@
 -- | Path to default CSS file.
 defaultCssFile :: FilePath -> FilePath
 defaultCssFile libdir = libdir </> "html" </> "solarized.css"
-
diff --git a/src/Haddock/Backends/Hyperlinker/Parser.hs b/src/Haddock/Backends/Hyperlinker/Parser.hs
--- a/src/Haddock/Backends/Hyperlinker/Parser.hs
+++ b/src/Haddock/Backends/Hyperlinker/Parser.hs
@@ -10,14 +10,17 @@
 
 import qualified Data.ByteString as BS
 
+import GHC.Platform
 import GHC.Types.SourceText
 import GHC.Driver.Session
+import GHC.Driver.Config.Diagnostic
 import GHC.Utils.Error     ( pprLocMsgEnvelope )
 import GHC.Data.FastString ( mkFastString )
-import GHC.Parser.Errors.Ppr ( pprError )
+import GHC.Parser.Errors.Ppr ()
+import qualified GHC.Types.Error as E
 import GHC.Parser.Lexer    as Lexer
                            ( P(..), ParseResult(..), PState(..), Token(..)
-                           , initParserState, lexer, mkParserOpts, getErrorMessages)
+                           , initParserState, lexer, mkParserOpts, getPsErrorMessages)
 import GHC.Data.Bag         ( bagToList )
 import GHC.Utils.Outputable ( text, ($$) )
 import GHC.Utils.Panic      ( panic )
@@ -40,7 +43,7 @@
 parse dflags fpath bs = case unP (go False []) initState of
     POk _ toks -> reverse toks
     PFailed pst ->
-      let err:_ = bagToList (fmap pprError (getErrorMessages pst)) in
+      let err:_ = bagToList (E.getMessages $ getPsErrorMessages pst) in
       panic $ showSDoc dflags $
         text "Hyperlinker parse error:" $$ pprLocMsgEnvelope err
   where
@@ -48,8 +51,10 @@
     initState = initParserState pflags buf start
     buf = stringBufferFromByteString bs
     start = mkRealSrcLoc (mkFastString fpath) 1 1
-    pflags = mkParserOpts   (warningFlags dflags)
-                            (extensionFlags dflags)
+    arch_os = platformArchOS (targetPlatform dflags)
+    pflags = mkParserOpts   (extensionFlags dflags)
+                            (initDiagOpts dflags)
+                            (supportedLanguagesAndExtensions arch_os)
                             (safeImportsOn dflags)
                             False -- lex Haddocks as comment tokens
                             True  -- produce comment tokens
@@ -233,6 +238,7 @@
     ITrequires             -> TkKeyword
 
     ITinline_prag       {} -> TkPragma
+    ITopaque_prag       {} -> TkPragma
     ITspec_prag         {} -> TkPragma
     ITspec_inline_prag  {} -> TkPragma
     ITsource_prag       {} -> TkPragma
@@ -263,6 +269,7 @@
     ITequal                -> TkGlyph
     ITlam                  -> TkGlyph
     ITlcase                -> TkGlyph
+    ITlcases               -> TkGlyph
     ITvbar                 -> TkGlyph
     ITlarrow            {} -> TkGlyph
     ITrarrow            {} -> TkGlyph
@@ -350,10 +357,7 @@
     ITeof                  -> TkUnknown
 
     ITlineComment       {} -> TkComment
-    ITdocCommentNext    {} -> TkComment
-    ITdocCommentPrev    {} -> TkComment
-    ITdocCommentNamed   {} -> TkComment
-    ITdocSection        {} -> TkComment
+    ITdocComment        {} -> TkComment
     ITdocOptions        {} -> TkComment
 
     -- The lexer considers top-level pragmas as comments (see `pragState` in
@@ -374,6 +378,7 @@
 inPragma False tok =
   case tok of
     ITinline_prag       {} -> True
+    ITopaque_prag       {} -> True
     ITspec_prag         {} -> True
     ITspec_inline_prag  {} -> True
     ITsource_prag       {} -> True
diff --git a/src/Haddock/Backends/Hyperlinker/Renderer.hs b/src/Haddock/Backends/Hyperlinker/Renderer.hs
--- a/src/Haddock/Backends/Hyperlinker/Renderer.hs
+++ b/src/Haddock/Backends/Hyperlinker/Renderer.hs
@@ -1,6 +1,5 @@
 {-# LANGUAGE RecordWildCards #-}
 {-# LANGUAGE ViewPatterns #-}
-{-# LANGUAGE PatternSynonyms #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE BangPatterns #-}
 
@@ -24,6 +23,7 @@
 
 import qualified Data.Map as Map
 import qualified Data.Set as Set
+import qualified Data.List as List
 
 import Text.XHtml (Html, HtmlAttr, (!))
 import qualified Text.XHtml as Html
@@ -141,8 +141,8 @@
 
     contexts = concatMap (Set.elems . identInfo) . Map.elems . nodeIdentifiers $ details
 
-    -- pick an arbitary non-evidence identifier to hyperlink with
-    identDet = Map.lookupMin $ Map.filter notEvidence $ nodeIdentifiers $ details
+    -- pick an arbitrary non-evidence identifier to hyperlink with
+    identDet = Map.lookupMin $ Map.filter notEvidence $ nodeIdentifiers details
     notEvidence = not . any isEvidenceContext . identInfo
 
     -- If we have name information, we can make links
@@ -249,14 +249,20 @@
     Left name -> externalModHyperlink name
 
   where
+    -- In a Nix environment, we have file:// URLs with absolute paths
+    makeHyperlinkUrl url | List.isPrefixOf "file://" url = url
+    makeHyperlinkUrl url = ".." </> url
+
     internalHyperlink name content =
         Html.anchor content ! [ Html.href $ "#" ++ internalAnchorIdent name ]
 
     externalNameHyperlink name content = case Map.lookup mdl srcs of
         Just SrcLocal -> Html.anchor content !
             [ Html.href $ hypSrcModuleNameUrl mdl name ]
-        Just (SrcExternal path) -> Html.anchor content !
-            [ Html.href $ spliceURL Nothing (Just mdl) (Just name) Nothing (".." </> path) ]
+        Just (SrcExternal path) ->
+          let hyperlinkUrl = makeHyperlinkUrl path </> hypSrcModuleNameUrl mdl name
+           in Html.anchor content !
+                [ Html.href $ spliceURL Nothing (Just mdl) (Just name) Nothing hyperlinkUrl ]
         Nothing -> content
       where
         mdl = nameModule name
@@ -265,8 +271,10 @@
         case Map.lookup moduleName srcs' of
           Just SrcLocal -> Html.anchor content !
             [ Html.href $ hypSrcModuleUrl' moduleName ]
-          Just (SrcExternal path) -> Html.anchor content !
-            [ Html.href $ spliceURL' Nothing (Just moduleName) Nothing Nothing (".." </> path) ]
+          Just (SrcExternal path) ->
+            let hyperlinkUrl = makeHyperlinkUrl path </> hypSrcModuleUrl' moduleName
+             in Html.anchor content !
+                  [ Html.href $ spliceURL' Nothing (Just moduleName) Nothing Nothing hyperlinkUrl ]
           Nothing -> content
 
 
diff --git a/src/Haddock/Backends/LaTeX.hs b/src/Haddock/Backends/LaTeX.hs
--- a/src/Haddock/Backends/LaTeX.hs
+++ b/src/Haddock/Backends/LaTeX.hs
@@ -24,7 +24,7 @@
 import GHC.Utils.Ppr hiding (Doc, quote)
 import qualified GHC.Utils.Ppr as Pretty
 
-import GHC.Types.Basic        ( PromotionFlag(..) )
+import GHC.Types.Basic        ( PromotionFlag(..), isPromoted )
 import GHC hiding (fromMaybeContext )
 import GHC.Types.Name.Occurrence
 import GHC.Types.Name        ( nameOccName )
@@ -843,7 +843,7 @@
     fieldPart = case con of
         ConDeclGADT{con_g_args = con_args'} -> case con_args' of
           -- GADT record declarations
-          RecConGADT _                    -> doConstrArgsWithDocs []
+          RecConGADT _ _                  -> doConstrArgsWithDocs []
           -- GADT prefix data constructors
           PrefixConGADT args | hasArgDocs -> doConstrArgsWithDocs (map hsScaledThing args)
           _                               -> empty
@@ -887,12 +887,12 @@
 -- | Pretty-print a record field
 ppSideBySideField :: [(DocName, DocForDecl DocName)] -> Bool -> ConDeclField DocNameI ->  LaTeX
 ppSideBySideField subdocs unicode (ConDeclField _ names ltype _) =
-  decltt (cat (punctuate comma (map (ppBinder . rdrNameOcc . unLoc . rdrNameFieldOcc . unLoc) names))
+  decltt (cat (punctuate comma (map (ppBinder . rdrNameOcc . unLoc . foLabel . unLoc) names))
     <+> dcolon unicode <+> ppLType unicode ltype) <-> rDoc mbDoc
   where
     -- don't use cd_fld_doc for same reason we don't use con_doc above
     -- Where there is more than one name, they all have the same documentation
-    mbDoc = lookup (extFieldOcc $ unLoc $ head names) subdocs >>= fmap _doc . combineDocumentation . fst
+    mbDoc = lookup (foExt $ unLoc $ head names) subdocs >>= fmap _doc . combineDocumentation . fst
 
 
 -- | Pretty-print a bundled pattern synonym
@@ -983,12 +983,13 @@
 -------------------------------------------------------------------------------
 
 
-ppLContext, ppLContextNoArrow :: Maybe (LHsContext DocNameI) -> Bool -> LaTeX
-ppLContext        Nothing _ = empty
-ppLContext        (Just ctxt) unicode  = ppContext        (unLoc ctxt) unicode
-ppLContextNoArrow Nothing _ = empty
-ppLContextNoArrow (Just ctxt) unicode = ppContextNoArrow (unLoc ctxt) unicode
+ppLContext :: Maybe (LHsContext DocNameI) -> Bool -> LaTeX
+ppLContext Nothing _ = empty
+ppLContext (Just ctxt) unicode  = ppContext (unLoc ctxt) unicode
 
+ppLContextNoArrow :: LHsContext DocNameI -> Bool -> LaTeX
+ppLContextNoArrow ctxt unicode = ppContextNoArrow (unLoc ctxt) unicode
+
 ppContextNoLocsMaybe :: [HsType DocNameI] -> Bool -> Maybe LaTeX
 ppContextNoLocsMaybe [] _ = Nothing
 ppContextNoLocsMaybe cxt unicode = Just $ pp_hs_context cxt unicode
@@ -1101,15 +1102,15 @@
   = sep [ ppHsForAllTelescope tele unicode
         , ppr_mono_lty ty unicode ]
 ppr_mono_ty (HsQualTy _ ctxt ty) unicode
-  = sep [ ppLContext ctxt unicode
+  = sep [ ppLContext (Just ctxt) unicode
         , ppr_mono_lty ty unicode ]
 ppr_mono_ty (HsFunTy _ mult ty1 ty2)   u
   = sep [ ppr_mono_lty ty1 u
         , arr <+> ppr_mono_lty ty2 u ]
    where arr = case mult of
-                 HsLinearArrow _ _ -> lollipop u
+                 HsLinearArrow _ -> lollipop u
                  HsUnrestrictedArrow _ -> arrow u
-                 HsExplicitMult _ _ m -> multAnnotation <> ppr_mono_lty m u <+> arrow u
+                 HsExplicitMult _ m _ -> multAnnotation <> ppr_mono_lty m u <+> arrow u
 
 ppr_mono_ty (HsBangTy _ b ty)     u = ppBang b <> ppLParendType u ty
 ppr_mono_ty (HsTyVar _ NotPromoted (L _ name)) _ = ppDocName name
@@ -1132,9 +1133,13 @@
 ppr_mono_ty (HsAppKindTy _ fun_ty arg_ki) unicode
   = hsep [ppr_mono_lty fun_ty unicode, atSign unicode <> ppr_mono_lty arg_ki unicode]
 
-ppr_mono_ty (HsOpTy _ ty1 op ty2) unicode
-  = ppr_mono_lty ty1 unicode <+> ppr_op <+> ppr_mono_lty ty2 unicode
+ppr_mono_ty (HsOpTy _ prom ty1 op ty2) unicode
+  = ppr_mono_lty ty1 unicode <+> ppr_op_prom <+> ppr_mono_lty ty2 unicode
   where
+    ppr_op_prom | isPromoted prom
+                = char '\'' <> ppr_op
+                | otherwise
+                = ppr_op
     ppr_op | isSymOcc (getOccName op) = ppLDocName op
            | otherwise = char '`' <> ppLDocName op <> char '`'
 
@@ -1260,7 +1265,7 @@
   , markupPic                  = \p _ -> inlineElem (markupPic p)
   , markupMathInline           = \p _ -> inlineElem (markupMathInline p)
   , markupMathDisplay          = \p _ -> blockElem (markupMathDisplay p)
-  , markupOrderedList          = \p v -> blockElem (enumeratedList (map (\p' -> p' v empty) p))
+  , markupOrderedList          = \p v -> blockElem (enumeratedList (map (\(_, p') -> p' v empty) p))
   , markupDefList              = \l v -> blockElem (descriptionList (map (\(a,b) -> (a v empty, b v empty)) l))
   , markupCodeBlock            = \p _ -> blockElem (quote (verb (p Verb empty)))
   , markupHyperlink            = \(Hyperlink u l) v -> inlineElem (markupLink u (fmap (\x -> x v empty) l))
@@ -1296,7 +1301,7 @@
       Just label -> text "\\href" <> braces (text url) <> braces label
       Nothing    -> text "\\url"  <> braces (text url)
 
-    -- Is there a better way of doing this? Just a space is an aribtrary choice.
+    -- Is there a better way of doing this? Just a space is an arbitrary choice.
     markupPic (Picture uri title) = parens (imageText title)
       where
         imageText Nothing = beg
@@ -1328,7 +1333,7 @@
 
 data StringContext
   = Plain  -- ^ all special characters have to be escape
-  | Mono   -- ^ on top of special characters, escape space chraacters
+  | Mono   -- ^ on top of special characters, escape space characters
   | Verb   -- ^ don't escape anything
 
 
@@ -1389,7 +1394,7 @@
 
 -- TODO: @verbatim@ is too much since
 --
---   * Haddock supports markup _inside_ of codeblocks. Right now, the LaTeX
+--   * Haddock supports markup _inside_ of code blocks. Right now, the LaTeX
 --     representing that markup gets printed verbatim
 --   * Verbatim environments are not supported everywhere (example: not nested
 --     inside a @tabulary@ environment)
diff --git a/src/Haddock/Backends/Xhtml.hs b/src/Haddock/Backends/Xhtml.hs
--- a/src/Haddock/Backends/Xhtml.hs
+++ b/src/Haddock/Backends/Xhtml.hs
@@ -11,10 +11,11 @@
 -- Stability   :  experimental
 -- Portability :  portable
 -----------------------------------------------------------------------------
-{-# LANGUAGE CPP, NamedFieldPuns #-}
+{-# LANGUAGE CPP, NamedFieldPuns, TupleSections, TypeApplications #-}
 module Haddock.Backends.Xhtml (
   ppHtml, copyHtmlBits,
   ppHtmlIndex, ppHtmlContents,
+  ppJsonIndex
 ) where
 
 
@@ -27,7 +28,9 @@
 import Haddock.Backends.Xhtml.Themes
 import Haddock.Backends.Xhtml.Types
 import Haddock.Backends.Xhtml.Utils
+import Haddock.InterfaceFile (PackageInfo (..), PackageInterfaces (..), ppPackageInfo)
 import Haddock.ModuleTree
+import Haddock.Options (Visibility (..))
 import Haddock.Types
 import Haddock.Version
 import Haddock.Utils
@@ -38,12 +41,16 @@
 
 import Control.Monad         ( when, unless )
 import qualified Data.ByteString.Builder as Builder
+import Data.Bifunctor        ( bimap )
 import Data.Char             ( toUpper, isSpace )
+import Data.Either           ( partitionEithers )
+import Data.Foldable         ( traverse_)
 import Data.List             ( sortBy, isPrefixOf, intersperse )
 import Data.Maybe
 import System.Directory
 import System.FilePath hiding ( (</>) )
 import qualified System.IO as IO
+import qualified System.FilePath as FilePath
 import Data.Map              ( Map )
 import qualified Data.Map as Map hiding ( Map )
 import qualified Data.Set as Set hiding ( Set )
@@ -68,10 +75,12 @@
        -> Maybe String                 -- ^ The mathjax URL (--mathjax)
        -> SourceURLs                   -- ^ The source URL (--source)
        -> WikiURLs                     -- ^ The wiki URL (--wiki)
+       -> BaseURL                      -- ^ The base URL (--base-url)
        -> Maybe String                 -- ^ The contents URL (--use-contents)
        -> Maybe String                 -- ^ The index URL (--use-index)
        -> Bool                         -- ^ Whether to use unicode in output (--use-unicode)
        -> Maybe String                 -- ^ Package name
+       -> PackageInfo                  -- ^ Package info
        -> QualOption                   -- ^ How to qualify names
        -> Bool                         -- ^ Output pretty html (newlines and indenting)
        -> Bool                         -- ^ Also write Quickjump index
@@ -79,8 +88,8 @@
 
 ppHtml state doctitle maybe_package ifaces reexported_ifaces odir prologue
         themes maybe_mathjax_url maybe_source_url maybe_wiki_url
-        maybe_contents_url maybe_index_url unicode
-        pkg qual debug withQuickjump = do
+        maybe_base_url maybe_contents_url maybe_index_url unicode
+        pkg packageInfo qual debug withQuickjump = do
   let
     visible_ifaces = filter visible ifaces
     visible i = OptHide `notElem` ifaceOptions i
@@ -88,22 +97,30 @@
   when (isNothing maybe_contents_url) $
     ppHtmlContents state odir doctitle maybe_package
         themes maybe_mathjax_url maybe_index_url maybe_source_url maybe_wiki_url
-        (map toInstalledIface visible_ifaces ++ reexported_ifaces)
+        withQuickjump
+        [PackageInterfaces
+          { piPackageInfo = packageInfo
+          , piVisibility  = Visible
+          , piInstalledInterfaces = map toInstalledIface visible_ifaces
+                                 ++ reexported_ifaces
+          }]
         False -- we don't want to display the packages in a single-package contents
         prologue debug pkg (makeContentsQual qual)
 
   when (isNothing maybe_index_url) $ do
     ppHtmlIndex odir doctitle maybe_package
       themes maybe_mathjax_url maybe_contents_url maybe_source_url maybe_wiki_url
+      withQuickjump
       (map toInstalledIface visible_ifaces ++ reexported_ifaces) debug
 
-    when withQuickjump $
-      ppJsonIndex odir maybe_source_url maybe_wiki_url unicode pkg qual
-        visible_ifaces
+  when withQuickjump $
+    ppJsonIndex odir maybe_source_url maybe_wiki_url unicode pkg qual
+      visible_ifaces []
 
   mapM_ (ppHtmlModule odir doctitle themes
-           maybe_mathjax_url maybe_source_url maybe_wiki_url
-           maybe_contents_url maybe_index_url unicode pkg qual debug) visible_ifaces
+           maybe_mathjax_url maybe_source_url maybe_wiki_url maybe_base_url
+           maybe_contents_url maybe_index_url withQuickjump
+           unicode pkg qual debug) visible_ifaces
 
 
 copyHtmlBits :: FilePath -> FilePath -> Themes -> Bool -> IO ()
@@ -119,16 +136,23 @@
   return ()
 
 
-headHtml :: String -> Themes -> Maybe String -> Html
-headHtml docTitle themes mathjax_url =
-  header <<
+headHtml :: String -> Themes -> Maybe String -> Maybe String -> Html
+headHtml docTitle themes mathjax_url base_url =
+      header ! (maybe [] (\url -> [identifier "head", strAttr "data-base-url" url ]) base_url)
+    <<
     [ meta ! [ httpequiv "Content-Type", content "text/html; charset=UTF-8"]
     , meta ! [ XHtml.name "viewport", content "width=device-width, initial-scale=1"]
     , thetitle << docTitle
-    , styleSheet themes
-    , thelink ! [ rel "stylesheet", thetype "text/css", href quickJumpCssFile] << noHtml
+    , styleSheet base_url themes
+    , thelink ! [ rel "stylesheet"
+                , thetype "text/css"
+                , href (withBaseURL base_url quickJumpCssFile) ]
+             << noHtml
     , thelink ! [ rel "stylesheet", thetype "text/css", href fontUrl] << noHtml
-    , script ! [src haddockJsFile, emptyAttr "async", thetype "text/javascript"] << noHtml
+    , script ! [ src (withBaseURL base_url haddockJsFile)
+               , emptyAttr "async"
+               , thetype "text/javascript" ]
+            << noHtml
     , script ! [thetype "text/x-mathjax-config"] << primHtml mjConf
     , script ! [src mjUrl, thetype "text/javascript"] << noHtml
     ]
@@ -142,6 +166,15 @@
                      ,   "}"
                      , "});" ]
 
+quickJumpButtonLi :: Bool  -- ^ With Quick Jump?
+                  -> Maybe Html
+-- The TypeScript should replace this <li> element, given its id. However, in
+-- case it does not, the element is given content here too.
+quickJumpButtonLi True = Just $ li ! [identifier "quick-jump-button"]
+  << anchor ! [href "#"] << "Quick Jump"
+
+quickJumpButtonLi False = Nothing
+
 srcButton :: SourceURLs -> Maybe Interface -> Maybe Html
 srcButton (Just src_base_url, _, _, _) Nothing =
   Just (anchor ! [href src_base_url] << "Source")
@@ -180,20 +213,18 @@
 bodyHtml :: String -> Maybe Interface
     -> SourceURLs -> WikiURLs
     -> Maybe String -> Maybe String
+    -> Bool  -- ^ With Quick Jump?
     -> Html -> Html
 bodyHtml doctitle iface
            maybe_source_url maybe_wiki_url
            maybe_contents_url maybe_index_url
+           withQuickjump
            pageContent =
   body << [
     divPackageHeader << [
       nonEmptySectionName << doctitle,
-      unordList (catMaybes [
-        srcButton maybe_source_url iface,
-        wikiButton maybe_wiki_url (ifaceMod <$> iface),
-        contentsButton maybe_contents_url,
-        indexButton maybe_index_url])
-            ! [theclass "links", identifier "page-menu"]
+      ulist ! [theclass "links", identifier "page-menu"]
+        << catMaybes (quickJumpButtonLi withQuickjump : otherButtonLis)
       ],
     divContent << pageContent,
     divFooter << paragraph << (
@@ -202,6 +233,13 @@
       (" version " ++ projectVersion)
       )
     ]
+ where
+  otherButtonLis = (fmap . fmap) (li <<)
+    [ srcButton maybe_source_url iface
+    , wikiButton maybe_wiki_url (ifaceMod <$> iface)
+    , contentsButton maybe_contents_url
+    , indexButton maybe_index_url
+    ]
 
 moduleInfo :: Interface -> Html
 moduleInfo iface =
@@ -264,30 +302,44 @@
    -> Maybe String
    -> SourceURLs
    -> WikiURLs
-   -> [InstalledInterface] -> Bool -> Maybe (MDoc GHC.RdrName)
+   -> Bool  -- ^ With Quick Jump?
+   -> [PackageInterfaces] -> Bool -> Maybe (MDoc GHC.RdrName)
    -> Bool
    -> Maybe Package  -- ^ Current package
    -> Qualification  -- ^ How to qualify names
    -> IO ()
 ppHtmlContents state odir doctitle _maybe_package
   themes mathjax_url maybe_index_url
-  maybe_source_url maybe_wiki_url ifaces showPkgs prologue debug pkg qual = do
-  let tree = mkModuleTree state showPkgs
-         [(instMod iface, toInstalledDescription iface)
-         | iface <- ifaces
-         , not (instIsSig iface)]
-      sig_tree = mkModuleTree state showPkgs
-         [(instMod iface, toInstalledDescription iface)
-         | iface <- ifaces
-         , instIsSig iface]
+  maybe_source_url maybe_wiki_url withQuickjump
+  packages showPkgs prologue debug pkg qual = do
+  let trees =
+        [ ( piPackageInfo pinfo
+          , mkModuleTree state showPkgs
+            [(instMod iface, toInstalledDescription iface)
+            | iface <- piInstalledInterfaces pinfo
+            , not (instIsSig iface)
+            ]
+          )
+        | pinfo <- packages
+        ]
+      sig_trees =
+        [ ( piPackageInfo pinfo
+          , mkModuleTree state showPkgs
+            [(instMod iface, toInstalledDescription iface)
+            | iface <- piInstalledInterfaces pinfo
+            , instIsSig iface
+            ]
+          )
+        | pinfo <- packages
+        ]
       html =
-        headHtml doctitle themes mathjax_url +++
+        headHtml doctitle themes mathjax_url Nothing +++
         bodyHtml doctitle Nothing
           maybe_source_url maybe_wiki_url
-          Nothing maybe_index_url << [
+          Nothing maybe_index_url withQuickjump << [
             ppPrologue pkg qual doctitle prologue,
-            ppSignatureTree pkg qual sig_tree,
-            ppModuleTree pkg qual tree
+            ppSignatureTrees pkg qual sig_trees,
+            ppModuleTrees pkg qual trees
           ]
   createDirectoryIfMissing True odir
   writeUtf8File (joinPath [odir, contentsHtmlFile]) (renderToString debug html)
@@ -302,17 +354,37 @@
 ppPrologue pkg qual title (Just doc) =
   divDescription << (h1 << title +++ docElement thediv (rdrDocToHtml pkg qual doc))
 
+ppSignatureTrees :: Maybe Package -> Qualification -> [(PackageInfo, [ModuleTree])] -> Html
+ppSignatureTrees _ _ tss | all (null . snd) tss = mempty
+ppSignatureTrees pkg qual [(info, ts)] = 
+  divPackageList << (sectionName << "Signatures" +++ ppSignatureTree pkg qual "n" info ts)
+ppSignatureTrees pkg qual tss =
+  divModuleList <<
+    (sectionName << "Signatures"
+     +++ concatHtml [ ppSignatureTree pkg qual("n."++show i++".") info ts
+                    | (i, (info, ts)) <- zip [(1::Int)..] tss
+                    ])
 
-ppSignatureTree :: Maybe Package -> Qualification -> [ModuleTree] -> Html
-ppSignatureTree _ _ [] = mempty
-ppSignatureTree pkg qual ts =
-  divModuleList << (sectionName << "Signatures" +++ mkNodeList pkg qual [] "n" ts)
+ppSignatureTree :: Maybe Package -> Qualification -> String -> PackageInfo -> [ModuleTree] -> Html
+ppSignatureTree _ _ _ _ [] = mempty
+ppSignatureTree pkg qual p info ts =
+  divModuleList << (sectionName << ppPackageInfo info +++ mkNodeList pkg qual [] p ts)
 
+ppModuleTrees :: Maybe Package -> Qualification -> [(PackageInfo, [ModuleTree])] -> Html
+ppModuleTrees _ _ tss | all (null . snd) tss = mempty
+ppModuleTrees pkg qual [(info, ts)] =
+  divModuleList << (sectionName << "Modules" +++ ppModuleTree pkg qual "n" info ts)
+ppModuleTrees pkg qual tss =
+  divPackageList <<
+    (sectionName << "Packages"
+     +++ concatHtml [ppModuleTree pkg qual ("n."++show i++".") info ts
+                    | (i, (info, ts)) <- zip [(1::Int)..] tss
+                    ])
 
-ppModuleTree :: Maybe Package -> Qualification -> [ModuleTree] -> Html
-ppModuleTree _ _ [] = mempty
-ppModuleTree pkg qual ts =
-  divModuleList << (sectionName << "Modules" +++ mkNodeList pkg qual [] "n" ts)
+ppModuleTree :: Maybe Package -> Qualification -> String -> PackageInfo -> [ModuleTree] -> Html
+ppModuleTree _ _ _ _ [] = mempty
+ppModuleTree pkg qual p info ts =
+  divModuleList << (sectionName << ppPackageInfo info +++ mkNodeList pkg qual [] p ts)
 
 
 mkNodeList :: Maybe Package -> Qualification -> [String] -> String -> [ModuleTree] -> Html
@@ -361,6 +433,35 @@
 -- * Generate the index
 --------------------------------------------------------------------------------
 
+data JsonIndexEntry = JsonIndexEntry {
+      jieHtmlFragment :: String,
+      jieName         :: String,
+      jieModule       :: String,
+      jieLink         :: String
+    }
+  deriving Show
+
+instance ToJSON JsonIndexEntry where
+    toJSON JsonIndexEntry
+        { jieHtmlFragment
+        , jieName
+        , jieModule
+        , jieLink } =
+      Object
+        [ "display_html" .= String jieHtmlFragment
+        , "name"         .= String jieName
+        , "module"       .= String jieModule
+        , "link"         .= String jieLink
+        ]
+
+instance FromJSON JsonIndexEntry where
+    parseJSON = withObject "JsonIndexEntry" $ \v ->
+      JsonIndexEntry
+        <$> v .: "display_html"
+        <*> v .: "name"
+        <*> v .: "module"
+        <*> v .: "link"
+
 ppJsonIndex :: FilePath
            -> SourceURLs                   -- ^ The source URL (--source)
            -> WikiURLs                     -- ^ The wiki URL (--wiki)
@@ -368,34 +469,55 @@
            -> Maybe Package
            -> QualOption
            -> [Interface]
+           -> [FilePath]                   -- ^ file paths to interface files
+                                           -- (--read-interface)
            -> IO ()
-ppJsonIndex odir maybe_source_url maybe_wiki_url unicode pkg qual_opt ifaces = do
+ppJsonIndex odir maybe_source_url maybe_wiki_url unicode pkg qual_opt ifaces installedIfacesPaths = do
   createDirectoryIfMissing True odir
-  IO.withBinaryFile (joinPath [odir, indexJsonFile]) IO.WriteMode $ \h -> do
-    Builder.hPutBuilder h (encodeToBuilder modules)
+  (errors, installedIndexes) <-
+    partitionEithers
+      <$> traverse
+            (\ifaceFile -> do
+              let indexFile = takeDirectory ifaceFile
+                    FilePath.</> "doc-index.json"
+              a <- doesFileExist indexFile
+              if a then
+                    bimap (indexFile,) (map (fixLink ifaceFile))
+                <$> eitherDecodeFile @[JsonIndexEntry] indexFile
+                   else
+                    return (Right [])
+            )
+            installedIfacesPaths
+  traverse_ (\(indexFile, err) -> putStrLn $ "haddock: Coudn't parse " ++ indexFile ++ ": " ++ err)
+            errors
+  IO.withBinaryFile (joinPath [odir, indexJsonFile]) IO.WriteMode $ \h ->
+      Builder.hPutBuilder
+        h (encodeToBuilder (encodeIndexes (concat installedIndexes)))
   where
-    modules :: Value
-    modules = Array (concatMap goInterface ifaces)
+    encodeIndexes :: [JsonIndexEntry] -> Value
+    encodeIndexes installedIndexes =
+      toJSON
+        (concatMap fromInterface ifaces
+         ++ installedIndexes)
 
-    goInterface :: Interface -> [Value]
-    goInterface iface =
-        concatMap (goExport mdl qual) (ifaceRnExportItems iface)
+    fromInterface :: Interface -> [JsonIndexEntry]
+    fromInterface iface =
+        mkIndex mdl qual `mapMaybe` ifaceRnExportItems iface
       where
         aliases = ifaceModuleAliases iface
         qual    = makeModuleQual qual_opt aliases mdl
         mdl     = ifaceMod iface
 
-    goExport :: Module -> Qualification -> ExportItem DocNameI -> [Value]
-    goExport mdl qual item
+    mkIndex :: Module -> Qualification -> ExportItem DocNameI -> Maybe JsonIndexEntry
+    mkIndex mdl qual item
       | Just item_html <- processExport True links_info unicode pkg qual item
-      = [ Object
-            [ "display_html" .= String (showHtmlFragment item_html)
-            , "name"         .= String (unwords (map getOccString names))
-            , "module"       .= String (moduleString mdl)
-            , "link"         .= String (fromMaybe "" (listToMaybe (map (nameLink mdl) names)))
-            ]
-        ]
-      | otherwise = []
+      = Just JsonIndexEntry
+          { jieHtmlFragment = showHtmlFragment item_html
+          , jieName         = unwords (map getOccString names)
+          , jieModule       = moduleString mdl
+          , jieLink         = fromMaybe "" (listToMaybe (map (nameLink mdl) names))
+          }
+      | otherwise = Nothing
       where
         names = exportName item ++ exportSubs item
 
@@ -413,6 +535,13 @@
 
     links_info = (maybe_source_url, maybe_wiki_url)
 
+    -- update link using relative path to output directory
+    fixLink :: FilePath
+            -> JsonIndexEntry -> JsonIndexEntry
+    fixLink ifaceFile jie = 
+      jie { jieLink = makeRelative odir (takeDirectory ifaceFile)
+                        FilePath.</> jieLink jie }
+
 ppHtmlIndex :: FilePath
             -> String
             -> Maybe String
@@ -421,11 +550,12 @@
             -> Maybe String
             -> SourceURLs
             -> WikiURLs
+            -> Bool  -- ^ With Quick Jump?
             -> [InstalledInterface]
             -> Bool
             -> IO ()
 ppHtmlIndex odir doctitle _maybe_package themes
-  maybe_mathjax_url maybe_contents_url maybe_source_url maybe_wiki_url ifaces debug = do
+  maybe_mathjax_url maybe_contents_url maybe_source_url maybe_wiki_url withQuickjump ifaces debug = do
   let html = indexPage split_indices Nothing
               (if split_indices then [] else index)
 
@@ -441,10 +571,10 @@
 
   where
     indexPage showLetters ch items =
-      headHtml (doctitle ++ " (" ++ indexName ch ++ ")") themes maybe_mathjax_url +++
+      headHtml (doctitle ++ " (" ++ indexName ch ++ ")") themes maybe_mathjax_url Nothing +++
       bodyHtml doctitle Nothing
         maybe_source_url maybe_wiki_url
-        maybe_contents_url Nothing << [
+        maybe_contents_url Nothing withQuickjump << [
           if showLetters then indexInitialLetterLinks else noHtml,
           if null items then noHtml else
             divIndex << [sectionName << indexName ch, buildIndex items]
@@ -541,12 +671,15 @@
 
 ppHtmlModule
         :: FilePath -> String -> Themes
-        -> Maybe String -> SourceURLs -> WikiURLs
-        -> Maybe String -> Maybe String -> Bool -> Maybe Package -> QualOption
+        -> Maybe String -> SourceURLs -> WikiURLs -> BaseURL
+        -> Maybe String -> Maybe String
+        -> Bool  -- ^ With Quick Jump?
+        -> Bool -> Maybe Package -> QualOption
         -> Bool -> Interface -> IO ()
 ppHtmlModule odir doctitle themes
-  maybe_mathjax_url maybe_source_url maybe_wiki_url
-  maybe_contents_url maybe_index_url unicode pkg qual debug iface = do
+  maybe_mathjax_url maybe_source_url maybe_wiki_url maybe_base_url
+  maybe_contents_url maybe_index_url withQuickjump
+  unicode pkg qual debug iface = do
   let
       mdl = ifaceMod iface
       aliases = ifaceModuleAliases iface
@@ -563,10 +696,10 @@
         = toHtml mdl_str
       real_qual = makeModuleQual qual aliases mdl
       html =
-        headHtml mdl_str_annot themes maybe_mathjax_url +++
+        headHtml mdl_str_annot themes maybe_mathjax_url maybe_base_url +++
         bodyHtml doctitle (Just iface)
           maybe_source_url maybe_wiki_url
-          maybe_contents_url maybe_index_url << [
+          maybe_contents_url maybe_index_url withQuickjump << [
             divModuleHeader << (moduleInfo iface +++ (sectionName << mdl_str_linked)),
             ifaceToHtml maybe_source_url maybe_wiki_url iface unicode pkg real_qual
           ]
diff --git a/src/Haddock/Backends/Xhtml/Decl.hs b/src/Haddock/Backends/Xhtml/Decl.hs
--- a/src/Haddock/Backends/Xhtml/Decl.hs
+++ b/src/Haddock/Backends/Xhtml/Decl.hs
@@ -167,7 +167,7 @@
         leader' = leader <+> ppForAllPart unicode qual tele
 
     do_args n leader (HsQualTy _ lctxt ltype)
-      | null (fromMaybeContext lctxt)
+      | null (unLoc lctxt)
       = do_largs n leader ltype
       | otherwise
       = (leader <+> ppLContextNoArrow lctxt unicode qual emptyCtxts, Nothing, [])
@@ -436,13 +436,15 @@
 -------------------------------------------------------------------------------
 
 
-ppLContext, ppLContextNoArrow :: Maybe (LHsContext DocNameI) -> Unicode
+ppLContext :: Maybe (LHsContext DocNameI) -> Unicode
                               -> Qualification -> HideEmptyContexts -> Html
 ppLContext        Nothing  u q h = ppContext        []        u q h
 ppLContext        (Just c) u q h = ppContext        (unLoc c) u q h
-ppLContextNoArrow Nothing  u q h = ppContextNoArrow []        u q h
-ppLContextNoArrow (Just c) u q h = ppContextNoArrow (unLoc c) u q h
 
+ppLContextNoArrow :: LHsContext DocNameI -> Unicode
+                              -> Qualification -> HideEmptyContexts -> Html
+ppLContextNoArrow c u q h = ppContextNoArrow (unLoc c) u q h
+
 ppContextNoArrow :: HsContext DocNameI -> Unicode -> Qualification -> HideEmptyContexts -> Html
 ppContextNoArrow cxt unicode qual emptyCtxts = fromMaybe noHtml $
                                                ppContextNoLocsMaybe (map unLoc cxt) unicode qual emptyCtxts
@@ -725,7 +727,7 @@
         L _ rtyp = dropWildCards typ
     -- Instance methods signatures are synified and thus don't have a useful
     -- SrcSpan value. Use the methods name location instead.
-    return $ ppSimpleSig links splice unicode qual HideEmptyContexts (getLocA $ head $ lnames) names rtyp
+    return $ ppSimpleSig links splice unicode qual HideEmptyContexts (getLocA $ head lnames) names rtyp
 
 
 lookupAnySubdoc :: Eq id1 => id1 -> [(id1, DocForDecl id2)] -> DocForDecl id2
@@ -967,7 +969,7 @@
     fieldPart = case con of
         ConDeclGADT{con_g_args = con_args'} -> case con_args' of
           -- GADT record declarations
-          RecConGADT _                    -> [ doConstrArgsWithDocs [] ]
+          RecConGADT _ _                  -> [ doConstrArgsWithDocs [] ]
           -- GADT prefix data constructors
           PrefixConGADT args | hasArgDocs -> [ doConstrArgsWithDocs args ]
           _                               -> []
@@ -1025,7 +1027,7 @@
 ppSideBySideField subdocs unicode qual (ConDeclField _ names ltype _) =
   ( hsep (punctuate comma [ ppBinder False (rdrNameOcc field)
                           | L _ name <- names
-                          , let field = (unLoc . rdrNameFieldOcc) name
+                          , let field = (unLoc . foLabel) name
                           ])
       <+> dcolon unicode
       <+> ppLType unicode qual HideEmptyContexts ltype
@@ -1035,12 +1037,12 @@
   where
     -- don't use cd_fld_doc for same reason we don't use con_doc above
     -- Where there is more than one name, they all have the same documentation
-    mbDoc = lookup (extFieldOcc $ unLoc $ head names) subdocs >>= combineDocumentation . fst
+    mbDoc = lookup (foExt $ unLoc $ head names) subdocs >>= combineDocumentation . fst
 
 
 ppShortField :: Bool -> Unicode -> Qualification -> ConDeclField DocNameI -> Html
 ppShortField summary unicode qual (ConDeclField _ names ltype _)
-  = hsep (punctuate comma (map ((ppBinder summary) . rdrNameOcc . unLoc . rdrNameFieldOcc . unLoc) names))
+  = hsep (punctuate comma (map ((ppBinder summary) . rdrNameOcc . unLoc . foLabel . unLoc) names))
     <+> dcolon unicode <+> ppLType unicode qual HideEmptyContexts ltype
 
 
@@ -1185,13 +1187,13 @@
     hasNonEmptyContext t =
       case unLoc t of
         HsForAllTy _ _ s -> hasNonEmptyContext s
-        HsQualTy _ cxt s -> if null (fromMaybeContext cxt) then hasNonEmptyContext s else True
+        HsQualTy _ cxt s -> if null (unLoc cxt) then hasNonEmptyContext s else True
         HsFunTy _ _ _ s    -> hasNonEmptyContext s
         _ -> False
     isFirstContextEmpty t =
       case unLoc t of
         HsForAllTy _ _ s -> isFirstContextEmpty s
-        HsQualTy _ cxt _ -> null (fromMaybeContext cxt)
+        HsQualTy _ cxt _ -> null (unLoc cxt)
         HsFunTy _ _ _ s    -> isFirstContextEmpty s
         _ -> False
 
@@ -1230,7 +1232,7 @@
   = ppForAllPart unicode qual tele <+> ppr_mono_lty ty unicode qual emptyCtxts
 
 ppr_mono_ty (HsQualTy _ ctxt ty) unicode qual emptyCtxts
-  = ppLContext ctxt unicode qual emptyCtxts <+> ppr_mono_lty ty unicode qual emptyCtxts
+  = ppLContext (Just ctxt) unicode qual emptyCtxts <+> ppr_mono_lty ty unicode qual emptyCtxts
 
 -- UnicodeSyntax alternatives
 ppr_mono_ty (HsTyVar _ _ (L _ name)) True _ _
@@ -1248,9 +1250,9 @@
        , arr <+> ppr_mono_lty ty2 u q e
        ]
    where arr = case mult of
-                 HsLinearArrow _ _ -> lollipop u
+                 HsLinearArrow _ -> lollipop u
                  HsUnrestrictedArrow _ -> arrow u
-                 HsExplicitMult _ _ m -> multAnnotation <> ppr_mono_lty m u q e <+> arrow u
+                 HsExplicitMult _ m _ -> multAnnotation <> ppr_mono_lty m u q e <+> arrow u
 
 ppr_mono_ty (HsTupleTy _ con tys) u q _ =
   tupleParens con (map (ppLType u q HideEmptyContexts) tys)
@@ -1279,15 +1281,15 @@
   = hsep [ppr_mono_lty fun_ty unicode qual HideEmptyContexts
          , atSign unicode <> ppr_mono_lty arg_ki unicode qual HideEmptyContexts]
 
-ppr_mono_ty (HsOpTy _ ty1 op ty2) unicode qual _
-  = ppr_mono_lty ty1 unicode qual HideEmptyContexts <+> ppr_op <+> ppr_mono_lty ty2 unicode qual HideEmptyContexts
+ppr_mono_ty (HsOpTy _ prom ty1 op ty2) unicode qual _
+  = ppr_mono_lty ty1 unicode qual HideEmptyContexts <+> ppr_op_prom <+> ppr_mono_lty ty2 unicode qual HideEmptyContexts
   where
-    -- `(:)` is valid in type signature only as constructor to promoted list
-    -- and needs to be quoted in code so we explicitly quote it here too.
-    ppr_op
-        | (getOccString . getName . unL) op == ":" = promoQuote ppr_op'
-        | otherwise = ppr_op'
-    ppr_op' = ppLDocName qual Infix op
+    ppr_op_prom
+        | isPromoted prom
+        = promoQuote ppr_op
+        | otherwise
+        = ppr_op
+    ppr_op = ppLDocName qual Infix op
 
 ppr_mono_ty (HsParTy _ ty) unicode qual emptyCtxts
   = parens (ppr_mono_lty ty unicode qual emptyCtxts)
diff --git a/src/Haddock/Backends/Xhtml/DocMarkup.hs b/src/Haddock/Backends/Xhtml/DocMarkup.hs
--- a/src/Haddock/Backends/Xhtml/DocMarkup.hs
+++ b/src/Haddock/Backends/Xhtml/DocMarkup.hs
@@ -46,7 +46,7 @@
   markupIdentifierUnchecked  = thecode . ppUncheckedLink qual,
   markupModule               = \(ModLink m lbl) ->
                                  let (mdl,ref) = break (=='#') m
-                                       -- Accomodate for old style
+                                       -- Accommodate for old style
                                        -- foo\#bar anchors
                                      mdl' = case reverse mdl of
                                               '\\':_ -> init mdl
@@ -57,7 +57,7 @@
   markupBold                 = strong,
   markupMonospaced           = thecode,
   markupUnorderedList        = unordList,
-  markupOrderedList          = ordList,
+  markupOrderedList          = makeOrdList,
   markupDefList              = defList,
   markupCodeBlock            = pre,
   markupHyperlink            = \(Hyperlink url mLabel)
@@ -112,9 +112,12 @@
         htmlPrompt = (thecode . toHtml $ ">>> ") ! [theclass "prompt"]
         htmlExpression = (strong . thecode . toHtml $ expression ++ "\n") ! [theclass "userinput"]
 
+    makeOrdList :: HTML a => [(Int, a)] -> Html
+    makeOrdList items = olist << map (\(index, a) -> li ! [intAttr "value" index] << a) items
+
 -- | We use this intermediate type to transform the input 'Doc' tree
 -- in an arbitrary way before rendering, such as grouping some
--- elements. This is effectivelly a hack to prevent the 'Doc' type
+-- elements. This is effectively a hack to prevent the 'Doc' type
 -- from changing if it is possible to recover the layout information
 -- we won't need after the fact.
 data Hack a id =
@@ -277,5 +280,5 @@
     fmtUnParagraphLists :: DocMarkup (Wrap a) (Doc a)
     fmtUnParagraphLists = idMarkup {
       markupUnorderedList = DocUnorderedList . map unParagraph,
-      markupOrderedList   = DocOrderedList   . map unParagraph
+      markupOrderedList   = DocOrderedList   . map (\(index, a) -> (index, unParagraph a))
       }
diff --git a/src/Haddock/Backends/Xhtml/Layout.hs b/src/Haddock/Backends/Xhtml/Layout.hs
--- a/src/Haddock/Backends/Xhtml/Layout.hs
+++ b/src/Haddock/Backends/Xhtml/Layout.hs
@@ -15,7 +15,7 @@
 
   divPackageHeader, divContent, divModuleHeader, divFooter,
   divTableOfContents, divDescription, divSynopsis, divInterface,
-  divIndex, divAlphabet, divModuleList, divContentsList,
+  divIndex, divAlphabet, divPackageList, divModuleList,  divContentsList,
 
   sectionName,
   nonEmptySectionName,
@@ -81,7 +81,7 @@
 
 divPackageHeader, divContent, divModuleHeader, divFooter,
   divTableOfContents, divDescription, divSynopsis, divInterface,
-  divIndex, divAlphabet, divModuleList, divContentsList
+  divIndex, divAlphabet, divPackageList, divModuleList, divContentsList
     :: Html -> Html
 
 divPackageHeader    = sectionDiv "package-header"
@@ -96,6 +96,7 @@
 divIndex            = sectionDiv "index"
 divAlphabet         = sectionDiv "alphabet"
 divModuleList       = sectionDiv "module-list"
+divPackageList      = sectionDiv "module-list"
 
 
 --------------------------------------------------------------------------------
@@ -219,7 +220,7 @@
   where
     wrap = ((h1 << "Orphan instances") +++)
     instTable = fmap (thediv ! [ identifier ("section." ++ id_) ] <<) . subTableSrc pkg qual lnks splice
-    id_ = makeAnchorId $ "orphans"
+    id_ = makeAnchorId "orphans"
 
 
 subInstHead :: String -- ^ Instance unique id (for anchor generation)
diff --git a/src/Haddock/Backends/Xhtml/Meta.hs b/src/Haddock/Backends/Xhtml/Meta.hs
--- a/src/Haddock/Backends/Xhtml/Meta.hs
+++ b/src/Haddock/Backends/Xhtml/Meta.hs
@@ -14,7 +14,7 @@
 
 -- | Writes a json encoded file containing additional
 -- information about the generated documentation. This
--- is useful for external tools (e.g. hackage).
+-- is useful for external tools (e.g., Hackage).
 writeHaddockMeta :: FilePath -> Bool -> IO ()
 writeHaddockMeta odir withQuickjump = do
   let
diff --git a/src/Haddock/Backends/Xhtml/Themes.hs b/src/Haddock/Backends/Xhtml/Themes.hs
--- a/src/Haddock/Backends/Xhtml/Themes.hs
+++ b/src/Haddock/Backends/Xhtml/Themes.hs
@@ -17,6 +17,7 @@
     where
 
 import Haddock.Options
+import Haddock.Backends.Xhtml.Types ( BaseURL, withBaseURL )
 
 import Control.Monad (liftM)
 import Data.Char (toLower)
@@ -176,13 +177,13 @@
 cssFiles ts = nub $ concatMap themeFiles ts
 
 
-styleSheet :: Themes -> Html
-styleSheet ts = toHtml $ zipWith mkLink rels ts
+styleSheet :: BaseURL -> Themes -> Html
+styleSheet base_url ts = toHtml $ zipWith mkLink rels ts
   where
     rels = "stylesheet" : repeat "alternate stylesheet"
     mkLink aRel t =
       thelink
-        ! [ href (themeHref t),  rel aRel, thetype "text/css",
+        ! [ href (withBaseURL base_url (themeHref t)),  rel aRel, thetype "text/css",
             XHtml.title (themeName t)
           ]
         << noHtml
diff --git a/src/Haddock/Backends/Xhtml/Types.hs b/src/Haddock/Backends/Xhtml/Types.hs
--- a/src/Haddock/Backends/Xhtml/Types.hs
+++ b/src/Haddock/Backends/Xhtml/Types.hs
@@ -12,6 +12,8 @@
 -----------------------------------------------------------------------------
 module Haddock.Backends.Xhtml.Types (
   SourceURLs, WikiURLs,
+  BaseURL,
+  withBaseURL,
   LinksInfo,
   Splice,
   Unicode,
@@ -20,12 +22,21 @@
 
 import Data.Map
 import GHC
+import qualified System.FilePath as FilePath
 
 
 -- the base, module and entity URLs for the source code and wiki links.
 type SourceURLs = (Maybe FilePath, Maybe FilePath, Map Unit FilePath, Map Unit FilePath)
 type WikiURLs = (Maybe FilePath, Maybe FilePath, Maybe FilePath)
 
+-- | base url for loading js, json, css resources.  The default is "."
+--
+type BaseURL = Maybe String
+
+-- TODO: we shouldn't use 'FilePath.</>'
+withBaseURL :: BaseURL -> String -> String
+withBaseURL Nothing        uri = uri
+withBaseURL (Just baseUrl) uri = baseUrl FilePath.</> uri
 
 -- The URL for source and wiki links
 type LinksInfo = (SourceURLs, WikiURLs)
diff --git a/src/Haddock/Convert.hs b/src/Haddock/Convert.hs
--- a/src/Haddock/Convert.hs
+++ b/src/Haddock/Convert.hs
@@ -19,8 +19,6 @@
   PrintRuntimeReps(..),
 ) where
 
-#include "HsVersions.h"
-
 import GHC.Data.Bag ( emptyBag )
 import GHC.Types.Basic ( TupleSort(..), PromotionFlag(..), DefMethSpec(..), TopLevelFlag(..) )
 import GHC.Types.SourceText (SourceText(..))
@@ -47,9 +45,9 @@
 import GHC.Builtin.Names ( hasKey, eqTyConKey, ipClassKey, tYPETyConKey
                  , liftedDataConKey, boxedRepDataConKey )
 import GHC.Types.Unique ( getUnique )
-import GHC.Utils.Misc ( chkAppend, debugIsOn, dropList, equalLength
+import GHC.Utils.Misc ( chkAppend, dropList, equalLength
                       , filterByList, filterOut )
-import GHC.Utils.Panic ( assertPanic )
+import GHC.Utils.Panic.Plain ( assert )
 import GHC.Types.Var
 import GHC.Types.Var.Set
 import GHC.Types.SrcLoc
@@ -126,7 +124,7 @@
            vs = tyConVisibleTyVars (classTyCon cl)
 
        in withErrs (lefts atTyClDecls) . TyClD noExtField $ ClassDecl
-         { tcdCtxt = synifyCtx (classSCTheta cl)
+         { tcdCtxt = Just $ synifyCtx (classSCTheta cl)
          , tcdLName = synifyNameN cl
          , tcdTyVars = synifyTyVars vs
          , tcdFixity = synifyFixity cl
@@ -304,7 +302,7 @@
   alg_deriv = []
   defn = HsDataDefn { dd_ext     = noExtField
                     , dd_ND      = alg_nd
-                    , dd_ctxt    = alg_ctx
+                    , dd_ctxt    = Just alg_ctx
                     , dd_cType   = Nothing
                     , dd_kindSig = kindSig
                     , dd_cons    = cons
@@ -343,14 +341,14 @@
 synifyInjectivityAnn _       _ NotInjective = Nothing
 synifyInjectivityAnn (Just lhs) tvs (Injective inj) =
     let rhs = map (noLocA . tyVarName) (filterByList inj tvs)
-    in Just $ noLoc $ InjectivityAnn noAnn (noLocA lhs) rhs
+    in Just $ noLocA $ InjectivityAnn noAnn (noLocA lhs) rhs
 
 synifyFamilyResultSig :: Maybe Name -> Kind -> LFamilyResultSig GhcRn
 synifyFamilyResultSig  Nothing    kind
-   | isLiftedTypeKind kind = noLoc $ NoSig noExtField
-   | otherwise = noLoc $ KindSig  noExtField (synifyKindSig kind)
+   | isLiftedTypeKind kind = noLocA $ NoSig noExtField
+   | otherwise = noLocA $ KindSig  noExtField (synifyKindSig kind)
 synifyFamilyResultSig (Just name) kind =
-   noLoc $ TyVarSig noExtField (noLocA $ KindedTyVar noAnn () (noLocA name) (synifyKindSig kind))
+   noLocA $ TyVarSig noExtField (noLocA $ KindedTyVar noAnn () (noLocA name) (synifyKindSig kind))
 
 -- User beware: it is your responsibility to pass True (use_gadt_syntax)
 -- for any constructor that would be misrepresented by omitting its
@@ -377,7 +375,7 @@
 
   -- skip any EqTheta, use 'orig'inal syntax
   ctx | null theta = Nothing
-      | otherwise = synifyCtx theta
+      | otherwise = Just $ synifyCtx theta
 
   linear_tys =
     zipWith (\ty bang ->
@@ -389,7 +387,7 @@
 
   field_tys = zipWith con_decl_field (dataConFieldLabels dc) linear_tys
   con_decl_field fl synTy = noLocA $
-    ConDeclField noAnn [noLoc $ FieldOcc (flSelector fl) (noLocA $ mkVarUnqual $ flLabel fl)] synTy
+    ConDeclField noAnn [noLocA $ FieldOcc (flSelector fl) (noLocA $ mkVarUnqual $ flLabel fl)] synTy
                  Nothing
 
   mk_h98_arg_tys :: Either ErrMsg (HsConDeclH98Details GhcRn)
@@ -403,7 +401,7 @@
 
   mk_gadt_arg_tys :: HsConDeclGADTDetails GhcRn
   mk_gadt_arg_tys
-    | use_named_field_syntax = RecConGADT (noLocA field_tys)
+    | use_named_field_syntax = RecConGADT (noLocA field_tys) noHsUniTok
     | otherwise              = PrefixConGADT (map hsUnrestricted linear_tys)
 
  -- finally we get synifyDataCon's result!
@@ -464,8 +462,8 @@
     mainSig t = synifySigType DeleteTopLevelQuantification vs t
     defSig t = synifySigType ImplicitizeForAll vs t
 
-synifyCtx :: [PredType] -> Maybe (LHsContext GhcRn)
-synifyCtx ts = Just (noLocA ( map (synifyType WithinType []) ts))
+synifyCtx :: [PredType] -> LHsContext GhcRn
+synifyCtx ts = noLocA ( map (synifyType WithinType []) ts)
 
 
 synifyTyVars :: [TyVar] -> LHsQTyVars GhcRn
@@ -608,23 +606,25 @@
              tTy | L _ (HsExplicitListTy _ IsPromoted tTy') <- stripKindSig tTy
                  -> noLocA $ HsExplicitListTy noExtField IsPromoted (hTy : tTy')
                  | otherwise
-                 -> noLocA $ HsOpTy noExtField hTy (noLocA $ getName tc) tTy
+                 -> noLocA $ HsOpTy noAnn IsPromoted hTy (noLocA $ getName tc) tTy
       -- ditto for implicit parameter tycons
       | tc `hasKey` ipClassKey
       , [name, ty] <- tys
       , Just x <- isStrLitTy name
-      = noLocA $ HsIParamTy noAnn (noLoc $ HsIPName x) (synifyType WithinType vs ty)
+      = noLocA $ HsIParamTy noAnn (noLocA $ HsIPName x) (synifyType WithinType vs ty)
       -- and equalities
       | tc `hasKey` eqTyConKey
       , [ty1, ty2] <- tys
-      = noLocA $ HsOpTy noExtField
+      = noLocA $ HsOpTy noAnn
+                       NotPromoted
                        (synifyType WithinType vs ty1)
                        (noLocA eqTyConName)
                        (synifyType WithinType vs ty2)
       -- and infix type operators
       | isSymOcc (nameOccName (getName tc))
       , ty1:ty2:tys_rest <- vis_tys
-      = mk_app_tys (HsOpTy noExtField
+      = mk_app_tys (HsOpTy noAnn
+                           prom
                            (synifyType WithinType vs ty1)
                            (noLocA $ getName tc)
                            (synifyType WithinType vs ty2))
@@ -799,9 +799,9 @@
 
 synifyMult :: [TyVar] -> Mult -> HsArrow GhcRn
 synifyMult vs t = case t of
-                    One  -> HsLinearArrow NormalSyntax Nothing
-                    Many -> HsUnrestrictedArrow NormalSyntax
-                    ty -> HsExplicitMult NormalSyntax Nothing (synifyType WithinType vs ty)
+                    One  -> HsLinearArrow (HsPct1 noHsTok noHsUniTok)
+                    Many -> HsUnrestrictedArrow noHsUniTok
+                    ty -> HsExplicitMult noHsTok (synifyType WithinType vs ty) noHsUniTok
 
 
 
@@ -933,8 +933,8 @@
 tcSplitForAllTysReqPreserveSynonyms ty =
   let (all_bndrs, body) = tcSplitSomeForAllTysPreserveSynonyms isVisibleArgFlag ty
       req_bndrs         = mapMaybe mk_req_bndr_maybe all_bndrs in
-  ASSERT( req_bndrs `equalLength` all_bndrs )
-  (req_bndrs, body)
+  assert ( req_bndrs `equalLength` all_bndrs)
+    (req_bndrs, body)
   where
     mk_req_bndr_maybe :: TyCoVarBinder -> Maybe ReqTVBinder
     mk_req_bndr_maybe (Bndr tv argf) = case argf of
@@ -946,8 +946,8 @@
 tcSplitForAllTysInvisPreserveSynonyms ty =
   let (all_bndrs, body) = tcSplitSomeForAllTysPreserveSynonyms isInvisibleArgFlag ty
       inv_bndrs         = mapMaybe mk_inv_bndr_maybe all_bndrs in
-  ASSERT( inv_bndrs `equalLength` all_bndrs )
-  (inv_bndrs, body)
+  assert ( inv_bndrs `equalLength` all_bndrs)
+    (inv_bndrs, body)
   where
     mk_inv_bndr_maybe :: TyCoVarBinder -> Maybe InvisTVBinder
     mk_inv_bndr_maybe (Bndr tv argf) = case argf of
diff --git a/src/Haddock/GhcUtils.hs b/src/Haddock/GhcUtils.hs
--- a/src/Haddock/GhcUtils.hs
+++ b/src/Haddock/GhcUtils.hs
@@ -1,5 +1,6 @@
-{-# LANGUAGE BangPatterns, StandaloneDeriving, FlexibleInstances, ViewPatterns #-}
+{-# LANGUAGE BangPatterns, FlexibleInstances #-}
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE TypeApplications #-}
 {-# LANGUAGE ScopedTypeVariables #-}
@@ -95,7 +96,7 @@
 ifTrueJust False = const Nothing
 
 sigName :: LSig GhcRn -> [IdP GhcRn]
-sigName (L _ sig) = sigNameNoLoc sig
+sigName (L _ sig) = sigNameNoLoc emptyOccEnv sig
 
 -- | Was this signature given by the user?
 isUserLSig :: forall p. UnXRec p => LSig p -> Bool
@@ -114,7 +115,7 @@
 -- instantiated at DocNameI instead of (GhcPass _).
 
 -- | Like 'hsTyVarName' from GHC API, but not instantiated at (GhcPass _)
-hsTyVarBndrName :: forall flag n. (XXTyVarBndr n ~ NoExtCon, UnXRec n)
+hsTyVarBndrName :: forall flag n. (XXTyVarBndr n ~ DataConCantHappen, UnXRec n)
                 => HsTyVarBndr flag n -> IdP n
 hsTyVarBndrName (UserTyVar _ _ name) = unXRec @n name
 hsTyVarBndrName (KindedTyVar _ _ name _) = unXRec @n name
@@ -135,7 +136,7 @@
 
 mkEmptySigType :: LHsType GhcRn -> LHsSigType GhcRn
 -- Dubious, because the implicit binders are empty even
--- though the type might have free varaiables
+-- though the type might have free variables
 mkEmptySigType lty@(L loc ty) = L loc $ case ty of
   HsForAllTy { hst_tele = HsForAllInvis { hsf_invis_bndrs = bndrs }
              , hst_body = body }
@@ -171,17 +172,17 @@
                  , sig_body  = theta_ty })
  where
    theta_ty | Just theta <- mcxt
-            = noLocA (HsQualTy { hst_xqual = noAnn, hst_ctxt = Just theta, hst_body = tau_ty })
+            = noLocA (HsQualTy { hst_xqual = noAnn, hst_ctxt = theta, hst_body = tau_ty })
             | otherwise
             = tau_ty
 
 --  tau_ty :: LHsType DocNameI
    tau_ty = case args of
-              RecConGADT flds -> mkFunTy (noLocA (HsRecTy noAnn (unLoc flds))) res_ty
+              RecConGADT flds _ -> mkFunTy (noLocA (HsRecTy noAnn (unLoc flds))) res_ty
               PrefixConGADT pos_args -> foldr mkFunTy res_ty (map hsScaledThing pos_args)
 
    mkFunTy :: LHsType DocNameI -> LHsType DocNameI -> LHsType DocNameI
-   mkFunTy a b = noLocA (HsFunTy noAnn (HsUnrestrictedArrow NormalSyntax) a b)
+   mkFunTy a b = noLocA (HsFunTy noAnn (HsUnrestrictedArrow noHsUniTok) a b)
 
 getGADTConType (ConDeclH98 {}) = panic "getGADTConType"
   -- Should only be called on ConDeclGADT
@@ -192,7 +193,7 @@
   case collectHsBindBinders CollNoDictBinders d of
     []       -> []
     (name:_) -> [name]
-getMainDeclBinderI (SigD _ d) = sigNameNoLoc d
+getMainDeclBinderI (SigD _ d) = sigNameNoLoc emptyOccEnv d
 getMainDeclBinderI (ForD _ (ForeignImport _ name _ _)) = [unLoc name]
 getMainDeclBinderI (ForD _ (ForeignExport _ _ _ _)) = []
 getMainDeclBinderI _ = []
@@ -226,12 +227,11 @@
                          , hst_ctxt = add_ctxt ctxt, hst_body = ty })
     go_ty (L loc ty)
        = L loc (HsQualTy { hst_xqual = noExtField
-                         , hst_ctxt = add_ctxt Nothing, hst_body = L loc ty })
+                         , hst_ctxt = add_ctxt (noLocA []), hst_body = L loc ty })
 
-    extra_pred = nlHsTyConApp Prefix cls (lHsQTyVarsToTypes tvs0)
+    extra_pred = nlHsTyConApp NotPromoted Prefix cls (lHsQTyVarsToTypes tvs0)
 
-    add_ctxt Nothing              = Just $ noLocA [extra_pred]
-    add_ctxt (Just (L loc preds)) = Just $ L loc (extra_pred : preds)
+    add_ctxt (L loc preds) = L loc (extra_pred : preds)
 
 addClassContext _ _ sig = sig   -- E.g. a MinimalSig is fine
 
@@ -284,14 +284,14 @@
 
           ConDeclGADT { con_g_args = con_args' } -> case con_args' of
             PrefixConGADT {} -> Just d
-            RecConGADT fields
+            RecConGADT fields _
               | all field_avail (unLoc fields) -> Just d
               | otherwise -> Just (d { con_g_args = PrefixConGADT (field_types $ unLoc fields) })
               -- see above
       where
         field_avail :: LConDeclField GhcRn -> Bool
         field_avail (L _ (ConDeclField _ fs _ _))
-            = all (\f -> extFieldOcc (unLoc f) `elem` names) fs
+            = all (\f -> foExt (unLoc f) `elem` names) fs
 
         field_types flds = [ hsUnrestricted t | L _ (ConDeclField _ _ t _) <- flds ]
 
@@ -356,9 +356,7 @@
   go p (HsQualTy x ctxt ty)
     = let p' [_] = PREC_CTX
           p' _   = PREC_TOP -- parens will get added anyways later...
-          ctxt' = case ctxt of
-            Nothing -> Nothing
-            Just c -> Just $ mapXRec @a (\xs -> map (goL (p' xs)) xs) c
+          ctxt' = mapXRec @a (\xs -> map (goL (p' xs)) xs) ctxt
       in paren p PREC_CTX $ HsQualTy x ctxt' (goL PREC_TOP ty)
     -- = paren p PREC_FUN $ HsQualTy x (fmap (mapXRec @a (map reparenLType)) ctxt) (reparenLType ty)
   go p (HsFunTy x w ty1 ty2)
@@ -367,8 +365,8 @@
     = paren p PREC_CON $ HsAppTy x (goL PREC_FUN fun_ty) (goL PREC_CON arg_ty)
   go p (HsAppKindTy x fun_ty arg_ki)
     = paren p PREC_CON $ HsAppKindTy x (goL PREC_FUN fun_ty) (goL PREC_CON arg_ki)
-  go p (HsOpTy x ty1 op ty2)
-    = paren p PREC_FUN $ HsOpTy x (goL PREC_OP ty1) op (goL PREC_OP ty2)
+  go p (HsOpTy x prom ty1 op ty2)
+    = paren p PREC_FUN $ HsOpTy x prom (goL PREC_OP ty1) op (goL PREC_OP ty2)
   go p (HsParTy _ t) = unXRec @a $ goL p t -- pretend the paren doesn't exist - it will be added back if needed
   go _ t@HsTyVar{} = t
   go _ t@HsStarTy{} = t
@@ -469,12 +467,12 @@
   children con =
     case getRecConArgs_maybe con of
       Nothing -> []
-      Just flds -> map (extFieldOcc . unLoc) $ concatMap (cd_fld_names . unLoc) (unLoc flds)
+      Just flds -> map (foExt . unLoc) $ concatMap (cd_fld_names . unLoc) (unLoc flds)
 
 instance Parent (TyClDecl GhcRn) where
   children d
     | isDataDecl  d = map unLoc $ concatMap (getConNames . unLoc)
-                              $ (dd_cons . tcdDataDefn) $ d
+                                $ (dd_cons . tcdDataDefn) d
     | isClassDecl d =
         map (unLoc . fdLName . unLoc) (tcdATs d) ++
         [ unLoc n | L _ (TypeSig _ ns _) <- tcdSigs d, n <- ns ]
@@ -556,7 +554,7 @@
 --
 -- /O(1)/
 takeStringBuffer :: Int -> StringBuffer -> ByteString
-takeStringBuffer !n !(S.StringBuffer fp _ cur) = BS.PS fp cur n
+takeStringBuffer !n (S.StringBuffer fp _ cur) = BS.PS fp cur n
 
 -- | Return the prefix of the first 'StringBuffer' that /isn't/ in the second
 -- 'StringBuffer'. **The behavior is undefined if the 'StringBuffers' use
diff --git a/src/Haddock/Interface.hs b/src/Haddock/Interface.hs
--- a/src/Haddock/Interface.hs
+++ b/src/Haddock/Interface.hs
@@ -46,7 +46,7 @@
 import Haddock.Utils (Verbosity (..), normal, out, verbose)
 
 import Control.Monad (unless, when)
-import Control.Monad.IO.Class (MonadIO, liftIO)
+import Control.Monad.IO.Class (MonadIO)
 import Data.IORef (atomicModifyIORef', newIORef, readIORef)
 import Data.List (foldl', isPrefixOf, nub)
 import Text.Printf (printf)
@@ -54,23 +54,16 @@
 import qualified Data.Set as Set
 
 import GHC hiding (verbosity)
-import GHC.Data.FastString (unpackFS)
-import GHC.Data.Graph.Directed (flattenSCCs)
-import GHC.Driver.Env (hsc_dflags, hsc_home_unit, hsc_logger, hsc_static_plugins, hsc_units)
+import GHC.Data.Graph.Directed
+import GHC.Driver.Env
 import GHC.Driver.Monad (modifySession, withTimingM)
 import GHC.Driver.Session hiding (verbosity)
 import GHC.HsToCore.Docs (getMainDeclBinder)
-import GHC.Plugins (Outputable, Plugin (..), PluginWithArgs (..), StaticPlugin (..), defaultPlugin, keepRenamedSource)
+import GHC.Plugins
 import GHC.Tc.Types (TcGblEnv (..), TcM)
 import GHC.Tc.Utils.Env (tcLookupGlobal)
 import GHC.Tc.Utils.Monad (getTopEnv, setGblEnv)
-import GHC.Types.Name (nameIsFromExternalPackage, nameOccName)
-import GHC.Types.Name.Occurrence (isTcOcc)
-import GHC.Types.Name.Reader (globalRdrEnvElts, greMangledName, unQualOK)
-import GHC.Unit.Module.Env (ModuleSet, emptyModuleSet, mkModuleSet, unionModuleSet)
-import GHC.Unit.Module.Graph (ModuleGraphNode (..))
-import GHC.Unit.Module.ModSummary (emsModSummary, isBootSummary)
-import GHC.Unit.Types (IsBootInterface (..))
+import GHC.Unit.Module.Graph
 import GHC.Utils.Error (withTiming)
 
 #if defined(mingw32_HOST_OS)
@@ -145,20 +138,19 @@
 
   let
     installHaddockPlugin :: HscEnv -> HscEnv
-    installHaddockPlugin hsc_env = hsc_env
-      {
-        hsc_dflags =
-          gopt_set (hsc_dflags hsc_env) Opt_PluginTrustworthy
-      , hsc_static_plugins =
-          haddockPlugin : hsc_static_plugins hsc_env
-      }
+    installHaddockPlugin hsc_env =
+      let
+        old_plugins = hsc_plugins hsc_env
+        new_plugins = old_plugins { staticPlugins = haddockPlugin : staticPlugins old_plugins }
+        hsc_env'    = hsc_env { hsc_plugins = new_plugins }
+      in hscUpdateFlags (flip gopt_set Opt_PluginTrustworthy) hsc_env'
 
   -- Note that we would rather use withTempSession but as long as we
   -- have the separate attachInstances step we need to keep the session
   -- alive to be able to find all the instances.
   modifySession installHaddockPlugin
 
-  targets <- mapM (\filePath -> guessTarget filePath Nothing) modules
+  targets <- mapM (\filePath -> guessTarget filePath Nothing Nothing) modules
   setTargets targets
 
   loadOk <- withTimingM "load" (const ()) $
@@ -173,13 +165,59 @@
       moduleSet <- liftIO getModules
 
       let
+        -- We topologically sort the module graph including boot files,
+        -- so it should be acylic (hopefully we failed much earlier if this is not the case)
+        -- We then filter out boot modules from the resultant topological sort
+        --
+        -- We do it this way to make 'buildHomeLinks' a bit more stable
+        -- 'buildHomeLinks' depends on the topological order of its input in order
+        -- to construct its result. In particular, modules closer to the bottom of
+        -- the dependency chain are to be prefered for link destinations.
+        --
+        -- If there are cycles in the graph, then this order is indeterminate
+        -- (the nodes in the cycle can be ordered in any way).
+        -- While 'topSortModuleGraph' does guarantee stability for equivalent
+        -- module graphs, seemingly small changes in the ModuleGraph can have
+        -- big impacts on the `LinkEnv` constructed.
+        --
+        -- For example, suppose
+        --  G1 = A.hs -> B.hs -> C.hs (where '->' denotes an import).
+        --
+        -- Then suppose C.hs is changed to have a cyclic dependency on A
+        --
+        --  G2 = A.hs -> B.hs -> C.hs -> A.hs-boot
+        --
+        -- For G1, `C.hs` is preferred for link destinations. However, for G2,
+        -- the topologically sorted order not taking into account boot files (so
+        -- C -> A) is completely indeterminate.
+        -- Using boot files to resolve cycles, we end up with the original order
+        -- [C, B, A] (in decreasing order of preference for links)
+        --
+        -- This exact case came up in testing for the 'base' package, where there
+        -- is a big module cycle involving 'Prelude' on windows, but the cycle doesn't
+        -- include 'Prelude' on non-windows platforms. This lead to drastically different
+        -- LinkEnv's (and failing haddockHtmlTests) across the platforms
+        --
+        -- In effect, for haddock users this behaviour (using boot files to eliminate cycles)
+        -- means that {-# SOURCE #-} imports no longer count towards re-ordering
+        -- the preference of modules for linking.
+        --
+        -- i.e. if module A imports B, then B is preferred over A,
+        -- but if module A {-# SOURCE #-} imports B, then we can't say the same.
+        --
+        go (AcyclicSCC (ModuleNode _ ms))
+          | NotBoot <- isBootSummary ms = [ms]
+          | otherwise = []
+        go (AcyclicSCC _) = []
+        go (CyclicSCC _) = error "haddock: module graph cyclic even with boot files"
+
         ifaces :: [Interface]
         ifaces =
           [ Map.findWithDefault
               (error "haddock:iface")
-              (ms_mod (emsModSummary ems))
+              (ms_mod ms)
               ifaceMap
-          | ModuleNode ems <- flattenSCCs $ topSortModuleGraph True modGraph Nothing
+          | ms <- concatMap go $ topSortModuleGraph False modGraph Nothing
           ]
 
       return (ifaces, moduleSet)
@@ -212,7 +250,7 @@
       | otherwise = do
           hsc_env <- getTopEnv
           ifaces <- liftIO $ readIORef ifaceMapRef
-          (iface, modules) <- withTiming (hsc_logger hsc_env) (hsc_dflags hsc_env)
+          (iface, modules) <- withTiming (hsc_logger hsc_env)
                                 "processModule" (const ()) $
             processModule1 verbosity flags ifaces instIfaceMap hsc_env mod_summary tc_gbl_env
 
@@ -266,9 +304,8 @@
 
   (!interface, messages) <- do
     logger <- getLogger
-    dflags <- getDynFlags
     {-# SCC createInterface #-}
-     withTiming logger dflags "createInterface" (const ()) $ runIfM (fmap Just . tcLookupGlobal) $
+     withTiming logger "createInterface" (const ()) $ runIfM (fmap Just . tcLookupGlobal) $
       createInterface1 flags unit_state mod_summary tc_gbl_env
         ifaces inst_ifaces
 
@@ -318,7 +355,7 @@
       ]
         where
           formatName :: SrcSpan -> HsDecl GhcRn -> String
-          formatName loc n = p (getMainDeclBinder n) ++ case loc of
+          formatName loc n = p (getMainDeclBinder emptyOccEnv n) ++ case loc of
             RealSrcSpan rss _ -> " (" ++ unpackFS (srcSpanFile rss) ++ ":" ++
               show (srcSpanStartLine rss) ++ ")"
             _ -> ""
@@ -356,7 +393,7 @@
 -- The interfaces are passed in in topologically sorted order, but we start
 -- by reversing the list so we can do a foldl.
 buildHomeLinks :: [Interface] -> LinkEnv
-buildHomeLinks ifaces = foldl upd Map.empty (reverse ifaces)
+buildHomeLinks ifaces = foldl' upd Map.empty (reverse ifaces)
   where
     upd old_env iface
       | OptHide    `elem` ifaceOptions iface = old_env
diff --git a/src/Haddock/Interface/AttachInstances.hs b/src/Haddock/Interface/AttachInstances.hs
--- a/src/Haddock/Interface/AttachInstances.hs
+++ b/src/Haddock/Interface/AttachInstances.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE MagicHash, BangPatterns #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# OPTIONS_GHC -Wno-incomplete-record-updates #-}
 {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
@@ -136,12 +135,12 @@
                                , expItemSubDocs = subDocs
                                } = e { expItemFixities =
       nubByName fst $ expItemFixities e ++
-      [ (n',f) | n <- getMainDeclBinder d
+      [ (n',f) | n <- getMainDeclBinder emptyOccEnv d
                , n' <- n : (map fst subDocs ++ patsyn_names)
                , f <- maybeToList (getFixity n')
       ] }
       where
-        patsyn_names = concatMap (getMainDeclBinder . fst) patsyns
+        patsyn_names = concatMap (getMainDeclBinder emptyOccEnv . fst) patsyns
 
     attachFixities e = e
     -- spanName: attach the location to the name that is the same file as the instance location
diff --git a/src/Haddock/Interface/Create.hs b/src/Haddock/Interface/Create.hs
--- a/src/Haddock/Interface/Create.hs
+++ b/src/Haddock/Interface/Create.hs
@@ -9,7 +9,6 @@
 {-# LANGUAGE RecordWildCards #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE StandaloneDeriving #-}
-{-# LANGUAGE TupleSections #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE ViewPatterns #-}
 {-# OPTIONS_GHC -Wwarn #-}
@@ -35,7 +34,7 @@
 import Haddock.Convert (PrintRuntimeReps (..), tyThingToLHsDecl)
 import Haddock.GhcUtils (addClassContext, filterSigNames, lHsQTyVarsToTypes, mkEmptySigType, moduleString, parents,
                          pretty, restrictTo, sigName, unL)
-import Haddock.Interface.LexParseRn (processDocString, processDocStringParas, processDocStrings, processModuleHeader)
+import Haddock.Interface.LexParseRn
 import Haddock.Options (Flag (..), modulePackageInfo)
 import Haddock.Types hiding (liftErrMsg)
 import Haddock.Utils (replace)
@@ -55,36 +54,35 @@
 import GHC hiding (lookupName)
 import GHC.Core.Class (ClassMinimalDef, classMinimalDef)
 import GHC.Core.ConLike (ConLike (..))
-import GHC.Data.FastString (bytesFS, unpackFS)
+import GHC.Data.FastString (unpackFS)
 import GHC.Driver.Ppr (showSDoc)
-import GHC.HsToCore.Docs hiding (mkMaps)
+import GHC.HsToCore.Docs hiding (mkMaps, unionArgMaps)
 import GHC.IORef (readIORef)
-import GHC.Parser.Annotation (IsUnicodeSyntax (..))
 import GHC.Stack (HasCallStack)
 import GHC.Tc.Types hiding (IfM)
 import GHC.Tc.Utils.Monad (finalSafeMode)
 import GHC.Types.Avail hiding (avail)
 import qualified GHC.Types.Avail as Avail
 import GHC.Types.Basic (PromotionFlag (..))
-import GHC.Types.Name (getOccString, getSrcSpan, isDataConName, isValName, nameIsLocalOrFrom, nameOccName)
+import GHC.Types.Name (getOccString, getSrcSpan, isDataConName, isValName, nameIsLocalOrFrom, nameOccName, emptyOccEnv)
 import GHC.Types.Name.Env (lookupNameEnv)
 import GHC.Types.Name.Reader (GlobalRdrEnv, greMangledName, lookupGlobalRdrEnv)
 import GHC.Types.Name.Set (elemNameSet, mkNameSet)
 import GHC.Types.SourceFile (HscSource (..))
 import GHC.Types.SourceText (SourceText (..), sl_fs)
+import GHC.Unit.Types
 import qualified GHC.Types.SrcLoc as SrcLoc
 import qualified GHC.Unit.Module as Module
 import GHC.Unit.Module.ModSummary (msHsFilePath)
-import GHC.Unit.Module.Warnings (WarningTxt (..), Warnings (..))
 import GHC.Unit.State (PackageName (..), UnitState, lookupModuleInAllUnits)
 import qualified GHC.Utils.Outputable as O
 import GHC.Utils.Panic (pprPanic)
-import GHC.HsToCore.Docs hiding (mkMaps)
 import GHC.Unit.Module.Warnings
+import GHC.Types.Unique.Map
 
 newtype IfEnv m = IfEnv
   {
-    -- | Lookup names in the enviroment.
+    -- | Lookup names in the environment.
     ife_lookup_name :: Name -> m (Maybe TyThing)
   }
 
@@ -257,7 +255,7 @@
 
   -- Process the top-level module header documentation.
   (!info, header_doc) <- liftErrMsg $ processModuleHeader dflags pkg_name
-    tcg_rdr_env safety (thMbDocStr <|> (unLoc <$> tcg_doc_hdr))
+    tcg_rdr_env safety (fmap hsDocString thMbDocStr <|> (hsDocString . unLoc <$> tcg_doc_hdr))
 
   -- Warnings on declarations in this module
   decl_warnings <- liftErrMsg (mkWarningMap dflags tcg_warns tcg_rdr_env exported_names)
@@ -266,7 +264,7 @@
   mod_warning <- liftErrMsg (moduleWarning dflags tcg_rdr_env tcg_warns)
 
   let
-    -- Warnings in this module and transitive warnings from dependend modules
+    -- Warnings in this module and transitive warnings from dependent modules
     warnings :: Map Name (Doc Name)
     warnings = M.unions (decl_warnings : map ifaceWarningMap (M.elems ifaces))
 
@@ -335,7 +333,7 @@
   M.fromList $
   mapMaybe (\(SrcLoc.L _ impDecl) -> do
     SrcLoc.L _ alias <- ideclAs impDecl
-    return $
+    return
       (lookupModuleDyn state
          -- TODO: This is supremely dodgy, because in general the
          -- UnitId isn't going to look anything like the package
@@ -351,8 +349,7 @@
          -- them to the user.  We should reuse that information;
          -- or at least reuse the renamed imports, which know what
          -- they import!
-         (fmap Module.fsToUnit $
-          fmap sl_fs $ ideclPkgQual impDecl)
+         (ideclPkgQual impDecl)
          (case ideclName impDecl of SrcLoc.L _ name -> name),
        alias))
     impDecls
@@ -395,11 +392,11 @@
 -- Similar to GHC.lookupModule
 -- ezyang: Not really...
 lookupModuleDyn ::
-  UnitState -> Maybe Unit -> ModuleName -> Module
-lookupModuleDyn _ (Just pkgId) mdlName =
-  Module.mkModule pkgId mdlName
-lookupModuleDyn state Nothing mdlName =
-  case lookupModuleInAllUnits state mdlName of
+  UnitState -> PkgQual -> ModuleName -> Module
+lookupModuleDyn state pkg_qual mdlName = case pkg_qual of
+  OtherPkg uid -> Module.mkModule (RealUnit (Definite uid)) mdlName
+  ThisPkg uid  -> Module.mkModule (RealUnit (Definite uid)) mdlName
+  NoPkgQual    -> case lookupModuleInAllUnits state mdlName of
     (m,_):_ -> m
     [] -> Module.mkModule Module.mainUnit mdlName
 
@@ -408,7 +405,7 @@
 -- Warnings
 -------------------------------------------------------------------------------
 
-mkWarningMap :: DynFlags -> Warnings -> GlobalRdrEnv -> [Name] -> ErrMsgM WarningMap
+mkWarningMap :: DynFlags -> Warnings a -> GlobalRdrEnv -> [Name] -> ErrMsgM WarningMap
 mkWarningMap dflags warnings gre exps = case warnings of
   NoWarnings  -> pure M.empty
   WarnAll _   -> pure M.empty
@@ -419,18 +416,18 @@
               , let n = greMangledName elt, n `elem` exps ]
     in M.fromList <$> traverse (bitraverse pure (parseWarning dflags gre)) ws'
 
-moduleWarning :: DynFlags -> GlobalRdrEnv -> Warnings -> ErrMsgM (Maybe (Doc Name))
+moduleWarning :: DynFlags -> GlobalRdrEnv -> Warnings a -> ErrMsgM (Maybe (Doc Name))
 moduleWarning _ _ NoWarnings = pure Nothing
 moduleWarning _ _ (WarnSome _) = pure Nothing
 moduleWarning dflags gre (WarnAll w) = Just <$> parseWarning dflags gre w
 
-parseWarning :: DynFlags -> GlobalRdrEnv -> WarningTxt -> ErrMsgM (Doc Name)
+parseWarning :: DynFlags -> GlobalRdrEnv -> WarningTxt a -> ErrMsgM (Doc Name)
 parseWarning dflags gre w = case w of
-  DeprecatedTxt _ msg -> format "Deprecated: " (foldMap (bytesFS . sl_fs . unLoc) msg)
-  WarningTxt    _ msg -> format "Warning: "    (foldMap (bytesFS . sl_fs . unLoc) msg)
+  DeprecatedTxt _ msg -> format "Deprecated: " (foldMap (unpackFS . sl_fs . hsDocString . unLoc) msg)
+  WarningTxt    _ msg -> format "Warning: "    (foldMap (unpackFS . sl_fs . hsDocString . unLoc) msg)
   where
     format x bs = DocWarning . DocParagraph . DocAppend (DocString x)
-                  <$> processDocString dflags gre (mkHsDocStringUtf8ByteString bs)
+                  <$> processDocStringFromString dflags gre bs
 
 
 -------------------------------------------------------------------------------
@@ -482,7 +479,7 @@
        -> Maybe Package  -- this package
        -> GlobalRdrEnv
        -> [Name]
-       -> [(LHsDecl GhcRn, [HsDocString])]
+       -> [(LHsDecl GhcRn, [HsDoc GhcRn])]
        -> ExtractedTHDocs -- ^ Template Haskell putDoc docs
        -> ErrMsgM Maps
 mkMaps dflags pkgName gre instances decls thDocs = do
@@ -515,36 +512,40 @@
     thMappings = do
       let ExtractedTHDocs
             _
-            (DeclDocMap declDocs)
-            (ArgDocMap argDocs)
-            (DeclDocMap instDocs) = thDocs
-          ds2mdoc :: HsDocString -> ErrMsgM (MDoc Name)
-          ds2mdoc = processDocStringParas dflags pkgName gre
+            declDocs
+            argDocs
+            instDocs = thDocs
+          ds2mdoc :: (HsDoc GhcRn) -> ErrMsgM (MDoc Name)
+          ds2mdoc = processDocStringParas dflags pkgName gre . hsDocString
 
-      declDocs' <- mapM ds2mdoc declDocs
-      argDocs'  <- mapM (mapM ds2mdoc) argDocs
-      instDocs' <- mapM ds2mdoc instDocs
+      let cvt = M.fromList . nonDetEltsUniqMap
+
+      declDocs' <- mapM ds2mdoc (cvt declDocs)
+      argDocs'  <- mapM (mapM ds2mdoc) (cvt argDocs)
+      instDocs' <- mapM ds2mdoc (cvt instDocs)
       return (declDocs' <> instDocs', argDocs')
 
 
-    mappings :: (LHsDecl GhcRn, [HsDocString])
+    mappings :: (LHsDecl GhcRn, [HsDoc GhcRn])
              -> ErrMsgM ( [(Name, MDoc Name)]
                         , [(Name, IntMap (MDoc Name))]
                         , [(Name,  [LHsDecl GhcRn])]
                         )
-    mappings (ldecl@(L (SrcSpanAnn _ (RealSrcSpan l _)) decl), docStrs) = do
-      let declDoc :: [HsDocString] -> IntMap HsDocString
+    mappings (ldecl@(L (SrcSpanAnn _ (RealSrcSpan l _)) decl), hs_docStrs) = do
+      let docStrs = map hsDocString hs_docStrs
+          declDoc :: [HsDocString] -> IntMap HsDocString
                   -> ErrMsgM (Maybe (MDoc Name), IntMap (MDoc Name))
           declDoc strs m = do
             doc' <- processDocStrings dflags pkgName gre strs
             m'   <- traverse (processDocStringParas dflags pkgName gre) m
             pure (doc', m')
 
-      (doc, args) <- declDoc docStrs (declTypeDocs decl)
+      (doc, args) <- declDoc docStrs (fmap hsDocString (declTypeDocs decl))
 
       let
           subs :: [(Name, [HsDocString], IntMap HsDocString)]
-          subs = subordinates instanceMap decl
+          subs = map (\(n, ds, im) -> (n, map hsDocString ds, fmap hsDocString im))
+                  $ subordinates emptyOccEnv instanceMap decl
 
       (subDocs, subArgs) <- unzip <$> traverse (\(_, strs, m) -> declDoc strs m) subs
 
@@ -575,8 +576,24 @@
               TyFamInstD _ (TyFamInstDecl _ d') -> getLocA (feqn_tycon d')
               _ -> getInstLoc d
     names l (DerivD {}) = maybeToList (M.lookup l instanceMap) -- See note [2].
-    names _ decl = getMainDeclBinder decl
+    names _ decl = getMainDeclBinder emptyOccEnv decl
 
+-- | Unions together two 'ArgDocMaps' (or ArgMaps in haddock-api), such that two
+-- maps with values for the same key merge the inner map as well.
+-- Left biased so @unionArgMaps a b@ prefers @a@ over @b@.
+
+unionArgMaps :: forall b . Map Name (IntMap b)
+             -> Map Name (IntMap b)
+             -> Map Name (IntMap b)
+unionArgMaps a b = M.foldrWithKey go b a
+  where
+    go :: Name -> IntMap b
+            -> Map Name (IntMap b) -> Map Name (IntMap b)
+    go n newArgMap acc
+      | Just oldArgMap <- M.lookup n acc =
+          M.insert n (newArgMap `IM.union` oldArgMap) acc
+      | otherwise = M.insert n newArgMap acc
+
 -- Note [2]:
 ------------
 -- We relate ClsInsts to InstDecls and DerivDecls using the SrcSpans buried
@@ -637,11 +654,11 @@
     Just exports -> liftM concat $ mapM lookupExport exports
   where
     lookupExport (IEGroup _ lev docStr, _)  = liftErrMsg $ do
-      doc <- processDocString dflags gre docStr
+      doc <- processDocString dflags gre (hsDocString . unLoc $ docStr)
       return [ExportGroup lev "" doc]
 
     lookupExport (IEDoc _ docStr, _)        = liftErrMsg $ do
-      doc <- processDocStringParas dflags pkgName gre docStr
+      doc <- processDocStringParas dflags pkgName gre (hsDocString . unLoc $ docStr)
       return [ExportDoc doc]
 
     lookupExport (IEDocNamed _ str, _)      = liftErrMsg $
@@ -709,7 +726,7 @@
           export <- hiValExportItem dflags t l doc (l `elem` splices) $ M.lookup t fixMap
           return [export]
         (ds, docs_) | decl : _ <- filter (not . isValD . unLoc) ds ->
-          let declNames = getMainDeclBinder (unL decl)
+          let declNames = getMainDeclBinder emptyOccEnv (unL decl)
           in case () of
             _
               -- We should not show a subordinate by itself if any of its
@@ -788,7 +805,7 @@
 
           let
             patSynNames =
-              concatMap (getMainDeclBinder . fst) bundledPatSyns
+              concatMap (getMainDeclBinder emptyOccEnv . fst) bundledPatSyns
 
             fixities =
                 [ (n, f)
@@ -1010,17 +1027,17 @@
   (concat . concat) `fmap` (for decls $ \decl -> do
     case decl of
       (L _ (DocD _ (DocGroup lev docStr))) -> do
-        doc <- liftErrMsg (processDocString dflags gre docStr)
+        doc <- liftErrMsg (processDocString dflags gre (hsDocString . unLoc $ docStr))
         return [[ExportGroup lev "" doc]]
       (L _ (DocD _ (DocCommentNamed _ docStr))) -> do
-        doc <- liftErrMsg (processDocStringParas dflags pkgName gre docStr)
+        doc <- liftErrMsg (processDocStringParas dflags pkgName gre (hsDocString . unLoc $ docStr))
         return [[ExportDoc doc]]
       (L _ (ValD _ valDecl))
         | name:_ <- collectHsBindBinders CollNoDictBinders valDecl
         , Just (L _ SigD{}:_) <- filter isSigD <$> M.lookup name declMap
         -> return []
       _ ->
-        for (getMainDeclBinder (unLoc decl)) $ \nm -> do
+        for (getMainDeclBinder emptyOccEnv (unLoc decl)) $ \nm -> do
           case lookupNameEnv availEnv nm of
             Just avail ->
               availExportItem is_sig modMap thisMod
@@ -1045,7 +1062,7 @@
   -> LHsDecl GhcRn             -- ^ parent declaration
   -> Either ErrMsg (LHsDecl GhcRn)
 extractDecl declMap name decl
-  | name `elem` getMainDeclBinder (unLoc decl) = pure decl
+  | name `elem` getMainDeclBinder emptyOccEnv (unLoc decl) = pure decl
   | otherwise  =
     case unLoc decl of
       TyClD _ d@ClassDecl { tcdLName = L _ clsNm
@@ -1113,15 +1130,14 @@
                                , Just rec <- map (getRecConArgs_maybe . unLoc) (dd_cons (feqn_rhs d))
                                , ConDeclField { cd_fld_names = ns } <- map unLoc (unLoc rec)
                                , L _ n <- ns
-                               , extFieldOcc n == name
+                               , foExt n == name
                           ]
             in case matches of
               [d0] -> extractDecl declMap name (noLocA . InstD noExtField $ DataFamInstD noExtField d0)
               _ -> Left "internal: extractDecl (ClsInstD)"
       _ -> Left ("extractDecl: Unhandled decl for " ++ getOccString name)
 
-extractPatternSyn :: HasCallStack
-                  => Name -> Name
+extractPatternSyn :: Name -> Name
                   -> [LHsTypeArg GhcRn] -> [LConDecl GhcRn]
                   -> Either ErrMsg (LSig GhcRn)
 extractPatternSyn nm t tvs cons =
@@ -1142,17 +1158,17 @@
               InfixCon arg1 arg2 -> map hsScaledThing [arg1, arg2]
             ConDeclGADT { con_g_args = con_args' } -> case con_args' of
               PrefixConGADT args' -> map hsScaledThing args'
-              RecConGADT (L _ fields) -> cd_fld_type . unLoc <$> fields
+              RecConGADT (L _ fields) _ -> cd_fld_type . unLoc <$> fields
         typ = longArrow args (data_ty con)
         typ' =
           case con of
-            ConDeclH98 { con_mb_cxt = Just cxt } -> noLocA (HsQualTy noExtField (Just cxt) typ)
+            ConDeclH98 { con_mb_cxt = Just cxt } -> noLocA (HsQualTy noExtField cxt typ)
             _ -> typ
-        typ'' = noLocA (HsQualTy noExtField Nothing typ')
+        typ'' = noLocA (HsQualTy noExtField (noLocA []) typ')
     in PatSynSig noAnn [noLocA nm] (mkEmptySigType typ'')
 
   longArrow :: [LHsType GhcRn] -> LHsType GhcRn -> LHsType GhcRn
-  longArrow inputs output = foldr (\x y -> noLocA (HsFunTy noAnn (HsUnrestrictedArrow NormalSyntax) x y)) output inputs
+  longArrow inputs output = foldr (\x y -> noLocA (HsFunTy noAnn (HsUnrestrictedArrow noHsUniTok) x y)) output inputs
 
   data_ty con
     | ConDeclGADT{} <- con = con_res_ty con
@@ -1169,12 +1185,12 @@
 extractRecSel nm t tvs (L _ con : rest) =
   case getRecConArgs_maybe con of
     Just (L _ fields) | ((l,L _ (ConDeclField _ _nn ty _)) : _) <- matching_fields fields ->
-      pure (L (noAnnSrcSpan l) (TypeSig noAnn [noLocA nm] (mkEmptyWildCardBndrs $ mkEmptySigType (noLocA (HsFunTy noAnn (HsUnrestrictedArrow NormalSyntax) data_ty (getBangType ty))))))
+      pure (L (noAnnSrcSpan l) (TypeSig noAnn [noLocA nm] (mkEmptyWildCardBndrs $ mkEmptySigType (noLocA (HsFunTy noAnn (HsUnrestrictedArrow noHsUniTok) data_ty (getBangType ty))))))
     _ -> extractRecSel nm t tvs rest
  where
   matching_fields :: [LConDeclField GhcRn] -> [(SrcSpan, LConDeclField GhcRn)]
-  matching_fields flds = [ (l,f) | f@(L _ (ConDeclField _ ns _ _)) <- flds
-                                 , L l n <- ns, extFieldOcc n == nm ]
+  matching_fields flds = [ (locA l,f) | f@(L _ (ConDeclField _ ns _ _)) <- flds
+                                      , L l n <- ns, foExt n == nm ]
   data_ty
     -- ResTyGADT _ ty <- con_res con = ty
     | ConDeclGADT{} <- con = con_res_ty con
@@ -1200,10 +1216,10 @@
   where
     exportName e@ExportDecl {} = name ++ subs ++ patsyns
       where subs    = map fst (expItemSubDocs e)
-            patsyns = concatMap (getMainDeclBinder . fst) (expItemPats e)
+            patsyns = concatMap (getMainDeclBinder emptyOccEnv . fst) (expItemPats e)
             name = case unLoc $ expItemDecl e of
               InstD _ d -> maybeToList $ SrcLoc.lookupSrcSpan (getInstLoc d) instMap
-              decl      -> getMainDeclBinder decl
+              decl      -> getMainDeclBinder emptyOccEnv decl
     exportName ExportNoDecl {} = [] -- we don't count these as visible, since
                                     -- we don't want links to go to them.
     exportName _ = []
@@ -1220,6 +1236,7 @@
       tell ["Cannot find documentation for: $" ++ name]
       return Nothing
     search (DocD _ (DocCommentNamed name' doc) : rest)
-      | name == name' = return (Just doc)
+      | name == name' = return (Just (hsDocString . unLoc $ doc))
+
       | otherwise = search rest
     search (_other_decl : rest) = search rest
diff --git a/src/Haddock/Interface/Json.hs b/src/Haddock/Interface/Json.hs
--- a/src/Haddock/Interface/Json.hs
+++ b/src/Haddock/Interface/Json.hs
@@ -130,8 +130,10 @@
 
 jsonDoc (DocOrderedList xs) = jsonObject
     [ ("tag", jsonString "DocOrderedList")
-    , ("documents", jsonArray (fmap jsonDoc xs))
+    , ("items", jsonArray (fmap jsonItem xs))
     ]
+  where
+    jsonItem (index, a) = jsonObject [("document", jsonDoc a), ("seq", jsonInt index)]
 
 jsonDoc (DocDefList xys) = jsonObject
     [ ("tag", jsonString "DocDefList")
diff --git a/src/Haddock/Interface/LexParseRn.hs b/src/Haddock/Interface/LexParseRn.hs
--- a/src/Haddock/Interface/LexParseRn.hs
+++ b/src/Haddock/Interface/LexParseRn.hs
@@ -15,6 +15,7 @@
 -----------------------------------------------------------------------------
 module Haddock.Interface.LexParseRn
   ( processDocString
+  , processDocStringFromString
   , processDocStringParas
   , processDocStrings
   , processModuleHeader
@@ -52,12 +53,16 @@
 
 processDocStringParas :: DynFlags -> Maybe Package -> GlobalRdrEnv -> HsDocString -> ErrMsgM (MDoc Name)
 processDocStringParas dflags pkg gre hds =
-  overDocF (rename dflags gre) $ parseParas dflags pkg (unpackHDS hds)
+  overDocF (rename dflags gre) $ parseParas dflags pkg (renderHsDocString hds)
 
 processDocString :: DynFlags -> GlobalRdrEnv -> HsDocString -> ErrMsgM (Doc Name)
 processDocString dflags gre hds =
-  rename dflags gre $ parseString dflags (unpackHDS hds)
+  processDocStringFromString dflags gre (renderHsDocString hds)
 
+processDocStringFromString :: DynFlags -> GlobalRdrEnv -> String -> ErrMsgM (Doc Name)
+processDocStringFromString dflags gre hds =
+  rename dflags gre $ parseString dflags hds
+
 processModuleHeader :: DynFlags -> Maybe Package -> GlobalRdrEnv -> SafeHaskellMode -> Maybe HsDocString
                     -> ErrMsgM (HaddockModInfo Name, Maybe (MDoc Name))
 processModuleHeader dflags pkgName gre safety mayStr = do
@@ -65,7 +70,7 @@
     case mayStr of
       Nothing -> return failure
       Just hds -> do
-        let str = unpackHDS hds
+        let str = renderHsDocString hds
             (hmi, doc) = parseModuleHeader dflags pkgName str
         !descr <- case hmi_description hmi of
                     Just hmi_descr -> Just <$> rename dflags gre hmi_descr
@@ -84,6 +89,10 @@
   where
     failure = (emptyHaddockModInfo, Nothing)
 
+traverseSnd :: (Traversable t, Applicative f) => (a -> f b) -> t (x, a) -> f (t (x, b))
+traverseSnd f = traverse (\(x, a) ->
+                             (\b -> (x, b)) <$> f a)
+
 -- | Takes a 'GlobalRdrEnv' which (hopefully) contains all the
 -- definitions and a parsed comment and we attempt to make sense of
 -- where the identifiers in the comment point to. We're in effect
@@ -146,7 +155,7 @@
       DocBold doc -> DocBold <$> rn doc
       DocMonospaced doc -> DocMonospaced <$> rn doc
       DocUnorderedList docs -> DocUnorderedList <$> traverse rn docs
-      DocOrderedList docs -> DocOrderedList <$> traverse rn docs
+      DocOrderedList docs -> DocOrderedList <$> traverseSnd rn docs
       DocDefList list -> DocDefList <$> traverse (\(a, b) -> (,) <$> rn a <*> rn b) list
       DocCodeBlock doc -> DocCodeBlock <$> rn doc
       DocIdentifierUnchecked x -> pure (DocIdentifierUnchecked x)
@@ -167,7 +176,7 @@
 -- 'GlobalReaderEnv' during 'rename') in an appropriate doc. Currently
 -- we simply monospace the identifier in most cases except when the
 -- identifier is qualified: if the identifier is qualified then we can
--- still try to guess and generate anchors accross modules but the
+-- still try to guess and generate anchors across modules but the
 -- users shouldn't rely on this doing the right thing. See tickets
 -- #253 and #375 on the confusion this causes depending on which
 -- default we pick in 'rename'.
diff --git a/src/Haddock/Interface/Rename.hs b/src/Haddock/Interface/Rename.hs
--- a/src/Haddock/Interface/Rename.hs
+++ b/src/Haddock/Interface/Rename.hs
@@ -191,8 +191,8 @@
   Documentation <$> mapM renameDoc mDoc <*> mapM renameDoc mWarning
 
 
-renameLDocHsSyn :: LHsDocString -> RnM LHsDocString
-renameLDocHsSyn = return
+renameLDocHsSyn :: Located (WithHsDocIdentifiers HsDocString a) -> RnM (Located (WithHsDocIdentifiers HsDocString b))
+renameLDocHsSyn (L l doc) = return (L l (WithHsDocIdentifiers (hsDocString doc) []))
 
 
 renameDoc :: Traversable t => t (Wrap Name) -> RnM (t (Wrap DocName))
@@ -245,9 +245,10 @@
 renameMaybeInjectivityAnn = traverse renameInjectivityAnn
 
 renameArrow :: HsArrow GhcRn -> RnM (HsArrow DocNameI)
-renameArrow (HsUnrestrictedArrow u) = return (HsUnrestrictedArrow u)
-renameArrow (HsLinearArrow u a) = return (HsLinearArrow u a)
-renameArrow (HsExplicitMult u a p) = HsExplicitMult u a <$> renameLType p
+renameArrow (HsUnrestrictedArrow arr) = return (HsUnrestrictedArrow arr)
+renameArrow (HsLinearArrow (HsPct1 pct1 arr)) = return (HsLinearArrow (HsPct1 pct1 arr))
+renameArrow (HsLinearArrow (HsLolly arr)) = return (HsLinearArrow (HsLolly arr))
+renameArrow (HsExplicitMult pct p arr) = (\p' -> HsExplicitMult pct p' arr) <$> renameLType p
 
 renameType :: HsType GhcRn -> RnM (HsType DocNameI)
 renameType t = case t of
@@ -258,7 +259,7 @@
                        , hst_tele = tele', hst_body = ltype' })
 
   HsQualTy { hst_ctxt = lcontext , hst_body = ltype } -> do
-    lcontext' <- traverse renameLContext lcontext
+    lcontext' <- renameLContext lcontext
     ltype'    <- renameLType ltype
     return (HsQualTy { hst_xqual = noAnn, hst_ctxt = lcontext', hst_body = ltype' })
 
@@ -289,11 +290,11 @@
   HsTupleTy _ b ts -> return . HsTupleTy noAnn b =<< mapM renameLType ts
   HsSumTy _ ts -> HsSumTy noAnn <$> mapM renameLType ts
 
-  HsOpTy _ a (L loc op) b -> do
+  HsOpTy _ prom a (L loc op) b -> do
     op' <- rename op
     a'  <- renameLType a
     b'  <- renameLType b
-    return (HsOpTy noAnn a' (L loc op') b')
+    return (HsOpTy noAnn prom a' (L loc op') b')
 
   HsParTy _ ty -> return . (HsParTy noAnn) =<< renameLType ty
 
@@ -316,6 +317,7 @@
   HsSpliceTy _ s          -> renameHsSpliceTy s
   HsWildCardTy _          -> pure (HsWildCardTy noAnn)
 
+
 renameSigType :: HsSigType GhcRn -> RnM (HsSigType DocNameI)
 renameSigType (HsSig { sig_bndrs = bndrs, sig_body = body }) = do
   bndrs' <- renameOuterTyVarBndrs bndrs
@@ -505,15 +507,15 @@
 renameCon decl@(ConDeclH98 { con_name = lname, con_ex_tvs = ltyvars
                            , con_mb_cxt = lcontext, con_args = details
                            , con_doc = mbldoc
-                           , con_forall = forall }) = do
+                           , con_forall = forall_ }) = do
       lname'    <- renameL lname
       ltyvars'  <- mapM renameLTyVarBndr ltyvars
       lcontext' <- traverse renameLContext lcontext
       details'  <- renameH98Details details
-      mbldoc'   <- mapM renameLDocHsSyn mbldoc
+      mbldoc'   <- mapM (renameLDocHsSyn) mbldoc
       return (decl { con_ext = noExtField, con_name = lname', con_ex_tvs = ltyvars'
                    , con_mb_cxt = lcontext'
-                   , con_forall = forall -- Remove when #18311 is fixed
+                   , con_forall = forall_ -- Remove when #18311 is fixed
                    , con_args = details', con_doc = mbldoc' })
 
 renameCon ConDeclGADT { con_names = lnames, con_bndrs = bndrs
@@ -548,9 +550,9 @@
 
 renameGADTDetails :: HsConDeclGADTDetails GhcRn
                   -> RnM (HsConDeclGADTDetails DocNameI)
-renameGADTDetails (RecConGADT (L l fields)) = do
+renameGADTDetails (RecConGADT (L l fields) arr) = do
   fields' <- mapM renameConDeclFieldField fields
-  return (RecConGADT (L (locA l) fields'))
+  return (RecConGADT (L (locA l) fields') arr)
 renameGADTDetails (PrefixConGADT ps) = PrefixConGADT <$> mapM renameHsScaled ps
 
 renameConDeclFieldField :: LConDeclField GhcRn -> RnM (LConDeclField DocNameI)
diff --git a/src/Haddock/Interface/Specialize.hs b/src/Haddock/Interface/Specialize.hs
--- a/src/Haddock/Interface/Specialize.hs
+++ b/src/Haddock/Interface/Specialize.hs
@@ -132,9 +132,9 @@
 
 
 sugarOperators :: HsType GhcRn -> HsType GhcRn
-sugarOperators (HsAppTy _ (L _ (HsAppTy _ (L _ (HsTyVar _ _ (L l name))) la)) lb)
-    | isSymOcc $ getOccName name' = mkHsOpTy la (L l name) lb
-    | unrestrictedFunTyConName == name' = HsFunTy noAnn (HsUnrestrictedArrow NormalSyntax) la lb
+sugarOperators (HsAppTy _ (L _ (HsAppTy _ (L _ (HsTyVar _ prom (L l name))) la)) lb)
+    | isSymOcc $ getOccName name' = mkHsOpTy prom la (L l name) lb
+    | unrestrictedFunTyConName == name' = HsFunTy noAnn (HsUnrestrictedArrow noHsUniTok) la lb
   where
     name' = getName name
 sugarOperators typ = typ
@@ -283,7 +283,7 @@
         <*> renameLType lt
 renameType (HsQualTy x lctxt lt) =
     HsQualTy x
-        <$> renameMContext lctxt
+        <$> renameLContext lctxt
         <*> renameLType lt
 renameType (HsTyVar x ip name) = HsTyVar x ip <$> locatedN renameName name
 renameType t@(HsStarTy _ _) = pure t
@@ -293,8 +293,8 @@
 renameType (HsListTy x lt) = HsListTy x <$> renameLType lt
 renameType (HsTupleTy x srt lt) = HsTupleTy x srt <$> mapM renameLType lt
 renameType (HsSumTy x lt) = HsSumTy x <$> mapM renameLType lt
-renameType (HsOpTy x la lop lb) =
-    HsOpTy x <$> renameLType la <*> locatedN renameName lop <*> renameLType lb
+renameType (HsOpTy x prom la lop lb) =
+    HsOpTy x prom <$> renameLType la <*> locatedN renameName lop <*> renameLType lb
 renameType (HsParTy x lt) = HsParTy x <$> renameLType lt
 renameType (HsIParamTy x ip lt) = HsIParamTy x ip <$> renameLType lt
 renameType (HsKindSig x lt lk) = HsKindSig x <$> renameLType lt <*> pure lk
@@ -311,7 +311,7 @@
 renameType (HsWildCardTy wc) = pure (HsWildCardTy wc)
 
 renameHsArrow :: HsArrow GhcRn -> Rename (IdP GhcRn) (HsArrow GhcRn)
-renameHsArrow (HsExplicitMult u a p) = HsExplicitMult u a <$> renameLType p
+renameHsArrow (HsExplicitMult pct p arr) = (\p' -> HsExplicitMult pct p' arr) <$> renameLType p
 renameHsArrow mult = pure mult
 
 
@@ -324,11 +324,10 @@
 renameLTypes :: [LHsType GhcRn] -> Rename (IdP GhcRn) [LHsType GhcRn]
 renameLTypes = mapM renameLType
 
-renameMContext :: Maybe (LHsContext GhcRn) -> Rename (IdP GhcRn) (Maybe (LHsContext GhcRn))
-renameMContext Nothing = return Nothing
-renameMContext (Just (L l ctxt)) = do
+renameLContext :: LHsContext GhcRn -> Rename (IdP GhcRn) (LHsContext GhcRn)
+renameLContext (L l ctxt) = do
   ctxt' <- renameContext ctxt
-  return (Just (L l ctxt'))
+  return (L l ctxt')
 
 renameContext :: HsContext GhcRn -> Rename (IdP GhcRn) (HsContext GhcRn)
 renameContext = renameLTypes
diff --git a/src/Haddock/InterfaceFile.hs b/src/Haddock/InterfaceFile.hs
--- a/src/Haddock/InterfaceFile.hs
+++ b/src/Haddock/InterfaceFile.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE CPP, RankNTypes, ScopedTypeVariables #-}
 {-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE NamedFieldPuns #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 -----------------------------------------------------------------------------
 -- |
@@ -15,43 +16,71 @@
 -- Reading and writing the .haddock interface file
 -----------------------------------------------------------------------------
 module Haddock.InterfaceFile (
-  InterfaceFile(..), ifUnitId, ifModule,
-  readInterfaceFile, nameCacheFromGhc, freshNameCache, NameCacheAccessor,
-  writeInterfaceFile, binaryInterfaceVersion, binaryInterfaceVersionCompatibility
+  InterfaceFile(..), PackageInfo(..), ifUnitId, ifModule,
+  PackageInterfaces(..), mkPackageInterfaces, ppPackageInfo,
+  readInterfaceFile, writeInterfaceFile,
+  freshNameCache,
+  binaryInterfaceVersion, binaryInterfaceVersionCompatibility
 ) where
 
 
 import Haddock.Types
 
-import Control.Monad
-import Control.Monad.IO.Class ( MonadIO(..) )
-import Data.Array
 import Data.IORef
-import Data.List (mapAccumR)
 import qualified Data.Map as Map
 import Data.Map (Map)
+import Data.Version
 import Data.Word
+import Text.ParserCombinators.ReadP (readP_to_S)
 
-import GHC.Iface.Binary (getSymtabName, getDictFastString)
+import GHC.Iface.Binary (getWithUserData, putSymbolTable)
+import GHC.Unit.State
 import GHC.Utils.Binary
 import GHC.Data.FastMutInt
 import GHC.Data.FastString
 import GHC hiding (NoLink)
-import GHC.Driver.Monad (withSession)
-import GHC.Driver.Env
 import GHC.Types.Name.Cache
-import GHC.Iface.Env
-import GHC.Types.Name
 import GHC.Types.Unique.FM
-import GHC.Types.Unique.Supply
 import GHC.Types.Unique
 
+import Haddock.Options (Visibility (..))
+
 data InterfaceFile = InterfaceFile {
   ifLinkEnv         :: LinkEnv,
+  -- | Package meta data.  Currently it only consist of a package name, which
+  -- is not read from the interface file, but inferred from its name.
+  --
+  -- issue #
+  ifPackageInfo     :: PackageInfo,
   ifInstalledIfaces :: [InstalledInterface]
 }
 
+data PackageInfo = PackageInfo {
+  piPackageName    :: PackageName,
+  piPackageVersion :: Data.Version.Version
+}
 
+ppPackageInfo :: PackageInfo -> String
+ppPackageInfo (PackageInfo name version) | version == makeVersion []
+                                         = unpackFS (unPackageName name)
+ppPackageInfo (PackageInfo name version) = unpackFS (unPackageName name) ++ "-" ++ showVersion version
+
+data PackageInterfaces = PackageInterfaces {
+  piPackageInfo         :: PackageInfo,
+  piVisibility          :: Visibility,
+  piInstalledInterfaces :: [InstalledInterface]
+}
+
+mkPackageInterfaces :: Visibility -> InterfaceFile -> PackageInterfaces
+mkPackageInterfaces piVisibility
+                    InterfaceFile { ifPackageInfo
+                                  , ifInstalledIfaces
+                                  } = 
+  PackageInterfaces { piPackageInfo = ifPackageInfo
+                    , piVisibility
+                    , piInstalledInterfaces = ifInstalledIfaces
+                    }
+
 ifModule :: InterfaceFile -> Module
 ifModule if_ =
   case ifInstalledIfaces if_ of
@@ -94,11 +123,11 @@
 -- (2) set `binaryInterfaceVersionCompatibility` to [binaryInterfaceVersion]
 --
 binaryInterfaceVersion :: Word16
-#if MIN_VERSION_ghc(9,2,0) && !MIN_VERSION_ghc(9,3,0)
-binaryInterfaceVersion = 38
+#if MIN_VERSION_ghc(9,4,0) && !MIN_VERSION_ghc(9,5,0)
+binaryInterfaceVersion = 41
 
 binaryInterfaceVersionCompatibility :: [Word16]
-binaryInterfaceVersionCompatibility = [37, binaryInterfaceVersion]
+binaryInterfaceVersionCompatibility = [binaryInterfaceVersion]
 #else
 #error Unsupported GHC version
 #endif
@@ -138,7 +167,7 @@
   let bh = setUserData bh0 $ newWriteState (putName bin_symtab)
                                            (putName bin_symtab)
                                            (putFastString bin_dict)
-  put_ bh iface
+  putInterfaceFile_ bh iface
 
   -- write the symtab pointer at the front of the file
   symtab_p <- tellBin bh
@@ -165,103 +194,31 @@
   return ()
 
 
-type NameCacheAccessor m = (m NameCache, NameCache -> m ())
-
-
-nameCacheFromGhc :: forall m. GhcMonad m => NameCacheAccessor m
-nameCacheFromGhc = ( read_from_session , write_to_session )
-  where
-    read_from_session = do
-       ref <- withSession (return . hsc_NC)
-       liftIO $ readIORef ref
-    write_to_session nc' = do
-       ref <- withSession (return . hsc_NC)
-       liftIO $ writeIORef ref nc'
-
-
-freshNameCache :: NameCacheAccessor IO
-freshNameCache = ( create_fresh_nc , \_ -> return () )
-  where
-    create_fresh_nc = do
-       u  <- mkSplitUniqSupply 'a' -- ??
-       return (initNameCache u [])
-
+freshNameCache :: IO NameCache
+freshNameCache = initNameCache 'a' -- ??
+                               []
 
 -- | Read a Haddock (@.haddock@) interface file. Return either an
 -- 'InterfaceFile' or an error message.
 --
 -- This function can be called in two ways.  Within a GHC session it will
 -- update the use and update the session's name cache.  Outside a GHC session
--- a new empty name cache is used.  The function is therefore generic in the
--- monad being used.  The exact monad is whichever monad the first
--- argument, the getter and setter of the name cache, requires.
---
-readInterfaceFile :: forall m.
-                     MonadIO m
-                  => NameCacheAccessor m
+-- a new empty name cache is used.
+readInterfaceFile :: NameCache
                   -> FilePath
                   -> Bool  -- ^ Disable version check. Can cause runtime crash.
-                  -> m (Either String InterfaceFile)
-readInterfaceFile (get_name_cache, set_name_cache) filename bypass_checks = do
-  bh0 <- liftIO $ readBinMem filename
-
-  magic   <- liftIO $ get bh0
-  version <- liftIO $ get bh0
-
-  case () of
-    _ | magic /= binaryInterfaceMagic -> return . Left $
-      "Magic number mismatch: couldn't load interface file: " ++ filename
-      | not bypass_checks
-      , (version `notElem` binaryInterfaceVersionCompatibility) -> return . Left $
-      "Interface file is of wrong version: " ++ filename
-      | otherwise -> with_name_cache $ \update_nc -> do
-
-      dict  <- get_dictionary bh0
-
-      -- read the symbol table so we are capable of reading the actual data
-      bh1 <- do
-          let bh1 = setUserData bh0 $ newReadState (error "getSymtabName")
-                                                   (getDictFastString dict)
-          symtab <- update_nc (get_symbol_table bh1)
-          return $ setUserData bh1 $ newReadState (getSymtabName (NCU (\f -> update_nc (return . f))) dict symtab)
-                                                  (getDictFastString dict)
-
-      -- load the actual data
-      iface <- liftIO $ get bh1
-      return (Right iface)
- where
-   with_name_cache :: forall a.
-                      ((forall n b. MonadIO n
-                                => (NameCache -> n (NameCache, b))
-                                -> n b)
-                       -> m a)
-                   -> m a
-   with_name_cache act = do
-      nc_var <-  get_name_cache >>= (liftIO . newIORef)
-      x <- act $ \f -> do
-              nc <- liftIO $ readIORef nc_var
-              (nc', x) <- f nc
-              liftIO $ writeIORef nc_var nc'
-              return x
-      liftIO (readIORef nc_var) >>= set_name_cache
-      return x
-
-   get_dictionary bin_handle = liftIO $ do
-      dict_p <- get bin_handle
-      data_p <- tellBin bin_handle
-      seekBin bin_handle dict_p
-      dict <- getDictionary bin_handle
-      seekBin bin_handle data_p
-      return dict
-
-   get_symbol_table bh1 theNC = liftIO $ do
-      symtab_p <- get bh1
-      data_p'  <- tellBin bh1
-      seekBin bh1 symtab_p
-      (nc', symtab) <- getSymbolTable bh1 theNC
-      seekBin bh1 data_p'
-      return (nc', symtab)
+                  -> IO (Either String InterfaceFile)
+readInterfaceFile name_cache filename bypass_checks = do
+  bh <- readBinMem filename
 
+  magic   <- get bh
+  if magic /= binaryInterfaceMagic
+    then return . Left $ "Magic number mismatch: couldn't load interface file: " ++ filename
+    else do
+      version <- get bh
+      if not bypass_checks && (version `notElem` binaryInterfaceVersionCompatibility)
+        then return . Left $ "Interface file is of wrong version: " ++ filename
+        else Right <$> getWithUserData name_cache bh
 
 -------------------------------------------------------------------------------
 -- * Symbol table
@@ -312,56 +269,6 @@
                                 -- indexed by FastString
   }
 
-
-putSymbolTable :: BinHandle -> Int -> UniqFM Name (Int,Name) -> IO ()
-putSymbolTable bh next_off symtab = do
-  put_ bh next_off
-  let names = elems (array (0,next_off-1) (eltsUFM symtab))
-  mapM_ (\n -> serialiseName bh n symtab) names
-
-
-getSymbolTable :: BinHandle -> NameCache -> IO (NameCache, Array Int Name)
-getSymbolTable bh namecache = do
-  sz <- get bh
-  od_names <- replicateM sz (get bh)
-  let arr = listArray (0,sz-1) names
-      (namecache', names) = mapAccumR (fromOnDiskName arr) namecache od_names
-  return (namecache', arr)
-
-
-type OnDiskName = (Unit, ModuleName, OccName)
-
-
-fromOnDiskName
-   :: Array Int Name
-   -> NameCache
-   -> OnDiskName
-   -> (NameCache, Name)
-fromOnDiskName _ nc (pid, mod_name, occ) =
-  let
-        modu  = mkModule pid mod_name
-        cache = nsNames nc
-  in
-  case lookupOrigNameCache cache modu occ of
-     Just name -> (nc, name)
-     Nothing   ->
-        let
-                us        = nsUniqs nc
-                u         = uniqFromSupply us
-                name      = mkExternalName u modu occ noSrcSpan
-                new_cache = extendNameCache cache modu occ name
-        in
-        case splitUniqSupply us of { (us',_) ->
-        ( nc{ nsUniqs = us', nsNames = new_cache }, name )
-        }
-
-
-serialiseName :: BinHandle -> Name -> UniqFM Name (Int,Name) -> IO ()
-serialiseName bh name _ = do
-  let modu = nameModule name
-  put_ bh (moduleUnit modu, moduleName modu, nameOccName name)
-
-
 -------------------------------------------------------------------------------
 -- * GhcBinary instances
 -------------------------------------------------------------------------------
@@ -371,17 +278,36 @@
   put_ bh m = put_ bh (Map.toList m)
   get bh = fmap (Map.fromList) (get bh)
 
+instance Binary PackageInfo where
+  put_ bh PackageInfo { piPackageName, piPackageVersion } = do
+    put_ bh (unPackageName piPackageName)
+    put_ bh (showVersion piPackageVersion)
+  get bh = do
+    name <- PackageName <$> get bh
+    versionString <- get bh
+    let version = case readP_to_S parseVersion versionString of
+          [] -> makeVersion []
+          vs -> fst (last vs)
+    return $ PackageInfo name version
 
 instance Binary InterfaceFile where
-  put_ bh (InterfaceFile env ifaces) = do
+  put_ bh (InterfaceFile env info ifaces) = do
     put_ bh env
+    put_ bh info
     put_ bh ifaces
 
   get bh = do
     env    <- get bh
+    info   <- get bh
     ifaces <- get bh
-    return (InterfaceFile env ifaces)
+    return (InterfaceFile env info ifaces)
 
+
+putInterfaceFile_ :: BinHandle -> InterfaceFile -> IO ()
+putInterfaceFile_ bh (InterfaceFile env info ifaces) = do
+  put_ bh env
+  put_ bh info
+  put_ bh ifaces
 
 instance Binary InstalledInterface where
   put_ bh (InstalledInterface modu is_sig info docMap argMap
diff --git a/src/Haddock/Options.hs b/src/Haddock/Options.hs
--- a/src/Haddock/Options.hs
+++ b/src/Haddock/Options.hs
@@ -15,6 +15,7 @@
 module Haddock.Options (
   parseHaddockOpts,
   Flag(..),
+  Visibility(..),
   getUsage,
   optTitle,
   outputDir,
@@ -24,6 +25,7 @@
   optSourceCssFile,
   sourceUrls,
   wikiUrls,
+  baseUrl,
   optParCount,
   optDumpInterfaceFile,
   optShowInterfaceFile,
@@ -72,6 +74,7 @@
   | Flag_SourceEntityURL  String
   | Flag_SourceLEntityURL String
   | Flag_WikiBaseURL   String
+  | Flag_BaseURL       String
   | Flag_WikiModuleURL String
   | Flag_WikiEntityURL String
   | Flag_LaTeX
@@ -157,6 +160,8 @@
       "URL for a source code link for each entity.\nUsed if name links are unavailable, eg. for TH splices.",
     Option []  ["comments-base"]   (ReqArg Flag_WikiBaseURL "URL")
       "URL for a comments link on the contents\nand index pages",
+    Option [] ["base-url"] (ReqArg Flag_BaseURL "URL")
+      "Base URL for static assets (eg. css, javascript, json files etc.).\nWhen given statis assets will not be copied.",
     Option []  ["comments-module"]  (ReqArg Flag_WikiModuleURL "URL")
       "URL for a comments link for each module\n(using the %{MODULE} var)",
     Option []  ["comments-entity"]  (ReqArg Flag_WikiEntityURL "URL")
@@ -301,6 +306,9 @@
   ,optLast [str | Flag_WikiEntityURL str <- flags])
 
 
+baseUrl :: [Flag] -> Maybe String
+baseUrl flags = optLast [str | Flag_BaseURL str <- flags]
+
 optDumpInterfaceFile :: [Flag] -> Maybe FilePath
 optDumpInterfaceFile flags = optLast [ str | Flag_DumpInterface str <- flags ]
 
@@ -354,18 +362,31 @@
 reexportFlags :: [Flag] -> [String]
 reexportFlags flags = [ option | Flag_Reexport option <- flags ]
 
+data Visibility = Visible | Hidden
+  deriving (Eq, Show)
 
-readIfaceArgs :: [Flag] -> [(DocPaths, FilePath)]
+readIfaceArgs :: [Flag] -> [(DocPaths, Visibility, FilePath)]
 readIfaceArgs flags = [ parseIfaceOption s | Flag_ReadInterface s <- flags ]
   where
-    parseIfaceOption :: String -> (DocPaths, FilePath)
+    parseIfaceOption :: String -> (DocPaths, Visibility, FilePath)
     parseIfaceOption str =
       case break (==',') str of
         (fpath, ',':rest) ->
           case break (==',') rest of
-            (src, ',':file) -> ((fpath, Just src), file)
-            (file, _) -> ((fpath, Nothing), file)
-        (file, _) -> (("", Nothing), file)
+            (src, ',':rest') ->
+              let src' = case src of
+                    "" -> Nothing
+                    _  -> Just src
+              in
+              case break (==',') rest' of
+                (visibility, ',':file) | visibility == "hidden" ->
+                  ((fpath, src'), Hidden, file)
+                                       | otherwise ->
+                  ((fpath, src'), Visible, file)
+                (file, _) ->
+                  ((fpath, src'), Visible, file)
+            (file, _) -> ((fpath, Nothing), Visible, file)
+        (file, _) -> (("", Nothing), Visible, file)
 
 
 -- | Like 'listToMaybe' but returns the last element instead of the first.
diff --git a/src/Haddock/Parser.hs b/src/Haddock/Parser.hs
--- a/src/Haddock/Parser.hs
+++ b/src/Haddock/Parser.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE ViewPatterns #-}
 -- |
 -- Module      :  Haddock.Parser
 -- Copyright   :  (c) Mateusz Kowalczyk 2013,
@@ -19,7 +18,7 @@
 import Haddock.Types
 
 import GHC.Driver.Session ( DynFlags )
-import GHC.Driver.Config
+import GHC.Driver.Config.Parser (initParserOpts)
 import GHC.Data.FastString   ( fsLit )
 import GHC.Parser.Lexer ( initParserState, unP, ParseResult(POk, PFailed) )
 import GHC.Parser       ( parseIdentifier )
diff --git a/src/Haddock/Types.hs b/src/Haddock/Types.hs
--- a/src/Haddock/Types.hs
+++ b/src/Haddock/Types.hs
@@ -1,4 +1,5 @@
-{-# LANGUAGE CPP, DeriveDataTypeable, DeriveFunctor, DeriveFoldable, DeriveTraversable, StandaloneDeriving, TypeFamilies, RecordWildCards #-}
+{-# LANGUAGE CPP, DeriveDataTypeable, DeriveTraversable, StandaloneDeriving, TypeFamilies, RecordWildCards #-}
+{-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE ConstraintKinds #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE PartialTypeSignatures #-}
@@ -150,7 +151,7 @@
     -- | Warnings for things defined in this module.
   , ifaceWarningMap :: !WarningMap
 
-    -- | Tokenized source code of module (avaliable if Haddock is invoked with
+    -- | Tokenized source code of module (available if Haddock is invoked with
     -- source generation flag).
   , ifaceHieFile :: !(Maybe FilePath)
   , ifaceDynFlags :: !DynFlags
@@ -319,7 +320,8 @@
 type instance IdP DocNameI = DocName
 
 instance CollectPass DocNameI where
-  collectXXPat _ _ ext = noExtCon ext
+  collectXXPat _ ext = dataConCantHappen ext
+  collectXXHsBindsLR ext = dataConCantHappen ext
 
 instance NamedThing DocName where
   getName (Documented name _) = name
@@ -709,8 +711,8 @@
 type instance Anno [LocatedA (HsType DocNameI)]      = SrcSpanAnnC
 type instance Anno (HsType DocNameI)                 = SrcSpanAnnA
 type instance Anno (DataFamInstDecl DocNameI)        = SrcSpanAnnA
-type instance Anno (DerivStrategy DocNameI)          = SrcSpan
-type instance Anno (FieldOcc DocNameI)               = SrcSpan
+type instance Anno (DerivStrategy DocNameI)          = SrcAnn NoEpAnns
+type instance Anno (FieldOcc DocNameI)               = SrcAnn NoEpAnns
 type instance Anno (ConDeclField DocNameI)           = SrcSpan
 type instance Anno (Located (ConDeclField DocNameI)) = SrcSpan
 type instance Anno [Located (ConDeclField DocNameI)] = SrcSpan
@@ -720,9 +722,9 @@
 type instance Anno [LocatedA (TyFamInstDecl DocNameI)] = SrcSpanAnnL
 type instance Anno (FamilyDecl DocNameI)               = SrcSpan
 type instance Anno (Sig DocNameI)                      = SrcSpan
-type instance Anno (InjectivityAnn DocNameI)           = SrcSpan
+type instance Anno (InjectivityAnn DocNameI)           = SrcAnn NoEpAnns
 type instance Anno (HsDecl DocNameI)                   = SrcSpanAnnA
-type instance Anno (FamilyResultSig DocNameI)          = SrcSpan
+type instance Anno (FamilyResultSig DocNameI)          = SrcAnn NoEpAnns
 type instance Anno (HsOuterTyVarBndrs Specificity DocNameI) = SrcSpanAnnA
 type instance Anno (HsSigType DocNameI)                     = SrcSpanAnnA
 
@@ -760,11 +762,11 @@
 
 type instance XHsForAllVis        DocNameI = NoExtField
 type instance XHsForAllInvis      DocNameI = NoExtField
-type instance XXHsForAllTelescope DocNameI = NoExtCon
+type instance XXHsForAllTelescope DocNameI = DataConCantHappen
 
 type instance XUserTyVar    DocNameI = NoExtField
 type instance XKindedTyVar  DocNameI = NoExtField
-type instance XXTyVarBndr   DocNameI = NoExtCon
+type instance XXTyVarBndr   DocNameI = DataConCantHappen
 
 type instance XCFieldOcc   DocNameI = DocName
 type instance XXFieldOcc   DocNameI = NoExtField
@@ -780,7 +782,7 @@
 type instance XForeignImport  DocNameI = NoExtField
 type instance XConDeclGADT    DocNameI = NoExtField
 type instance XConDeclH98     DocNameI = NoExtField
-type instance XXConDecl       DocNameI = NoExtCon
+type instance XXConDecl       DocNameI = DataConCantHappen
 
 type instance XDerivD     DocNameI = NoExtField
 type instance XInstD      DocNameI = NoExtField
@@ -791,10 +793,10 @@
 type instance XNoSig            DocNameI = NoExtField
 type instance XCKindSig         DocNameI = NoExtField
 type instance XTyVarSig         DocNameI = NoExtField
-type instance XXFamilyResultSig DocNameI = NoExtCon
+type instance XXFamilyResultSig DocNameI = DataConCantHappen
 
 type instance XCFamEqn       DocNameI _ = NoExtField
-type instance XXFamEqn       DocNameI _ = NoExtCon
+type instance XXFamEqn       DocNameI _ = DataConCantHappen
 
 type instance XCClsInstDecl DocNameI = NoExtField
 type instance XCDerivDecl   DocNameI = NoExtField
@@ -811,23 +813,24 @@
 type instance XDataDecl     DocNameI = NoExtField
 type instance XSynDecl      DocNameI = NoExtField
 type instance XFamDecl      DocNameI = NoExtField
-type instance XXFamilyDecl  DocNameI = NoExtCon
-type instance XXTyClDecl    DocNameI = NoExtCon
+type instance XXFamilyDecl  DocNameI = DataConCantHappen
+type instance XXTyClDecl    DocNameI = DataConCantHappen
 
 type instance XHsWC DocNameI _ = NoExtField
 
 type instance XHsOuterExplicit    DocNameI _ = NoExtField
 type instance XHsOuterImplicit    DocNameI   = NoExtField
-type instance XXHsOuterTyVarBndrs DocNameI   = NoExtCon
+type instance XXHsOuterTyVarBndrs DocNameI   = DataConCantHappen
 
 type instance XHsSig      DocNameI = NoExtField
-type instance XXHsSigType DocNameI = NoExtCon
+type instance XXHsSigType DocNameI = DataConCantHappen
 
 type instance XHsQTvs        DocNameI = NoExtField
 type instance XConDeclField  DocNameI = NoExtField
-type instance XXConDeclField DocNameI = NoExtCon
+type instance XXConDeclField DocNameI = DataConCantHappen
 
-type instance XXPat DocNameI = NoExtCon
+type instance XXPat DocNameI = DataConCantHappen
+type instance XXHsBindsLR DocNameI a = DataConCantHappen
 
 type instance XCInjectivityAnn DocNameI = NoExtField
 
diff --git a/src/Haddock/Utils/Json.hs b/src/Haddock/Utils/Json.hs
--- a/src/Haddock/Utils/Json.hs
+++ b/src/Haddock/Utils/Json.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RankNTypes        #-}
 
 -- | Minimal JSON / RFC 7159 support
 --
@@ -12,35 +13,53 @@
     , encodeToString
     , encodeToBuilder
     , ToJSON(toJSON)
+
+    , Parser(..)
+    , Result(..)
+    , FromJSON(parseJSON)
+    , withObject
+    , withArray
+    , withString
+    , withDouble
+    , withBool
+    , fromJSON
+    , parse
+    , parseEither
+    , (.:)
+    , (.:?)
+    , decode
+    , decodeWith
+    , eitherDecode
+    , eitherDecodeWith
+    , decodeFile
+    , eitherDecodeFile
     )
     where
 
+import Control.Applicative (Alternative (..))
+import Control.Monad (MonadPlus (..), zipWithM, (>=>))
+import qualified Control.Monad as Monad
+import qualified Control.Monad.Fail as Fail
+
+import qualified Data.ByteString.Lazy as BSL
+import Data.ByteString.Builder (Builder)
+import qualified Data.ByteString.Builder as BB
 import Data.Char
 import Data.Int
-import Data.String
 import Data.Word
 import Data.List (intersperse)
 import Data.Monoid
 
-import Data.ByteString.Builder (Builder)
-import qualified Data.ByteString.Builder as BB
+import GHC.Natural
 
 -- TODO: We may want to replace 'String' with 'Text' or 'ByteString'
 
--- | A JSON value represented as a Haskell value.
-data Value = Object !Object
-           | Array  [Value]
-           | String  String
-           | Number !Double
-           | Bool   !Bool
-           | Null
-           deriving (Eq, Read, Show)
+import qualified Text.Parsec.ByteString.Lazy as Parsec.Lazy
+import qualified Text.ParserCombinators.Parsec as Parsec
 
--- | A key\/value pair for an 'Object'
-type Pair = (String, Value)
+import Haddock.Utils.Json.Types
+import Haddock.Utils.Json.Parser
 
--- | A JSON \"object\" (key/value map).
-type Object = [Pair]
 
 infixr 8 .=
 
@@ -48,14 +67,7 @@
 (.=) :: ToJSON v => String -> v -> Pair
 k .= v  = (k, toJSON v)
 
--- | Create a 'Value' from a list of name\/value 'Pair's.
-object :: [Pair] -> Value
-object = Object
 
-instance IsString Value where
-  fromString = String
-
-
 -- | A type that can be converted to JSON.
 class ToJSON a where
   -- | Convert a Haskell value to a JSON-friendly intermediate type.
@@ -223,3 +235,324 @@
 
     -- unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
     needsEscape c = ord c < 0x20 || c `elem` ['\\','"']
+
+------------------------------------------------------------------------------
+-- FromJSON
+
+-- | Elements of a JSON path used to describe the location of an
+-- error.
+data JSONPathElement
+  = Key String
+  -- ^ JSON path element of a key into an object,
+  -- \"object.key\".
+  | Index !Int
+  -- ^ JSON path element of an index into an
+  -- array, \"array[index]\".
+  deriving (Eq, Show, Ord)
+
+type JSONPath = [JSONPathElement]
+
+-- | Failure continuation.
+type Failure f r   = JSONPath -> String -> f r
+
+-- | Success continuation.
+type Success a f r = a -> f r
+
+newtype Parser a = Parser {
+      runParser :: forall f r.
+                   JSONPath
+                -> Failure f r
+                -> Success a f r
+                -> f r
+    }
+
+modifyFailure :: (String -> String) -> Parser a -> Parser a
+modifyFailure f (Parser p) = Parser $ \path kf ks ->
+    p path (\p' m -> kf p' (f m)) ks
+
+prependFailure :: String -> Parser a -> Parser a
+prependFailure = modifyFailure . (++)
+
+prependContext :: String -> Parser a -> Parser a
+prependContext name = prependFailure ("parsing " ++ name ++ " failed, ")
+
+typeMismatch :: String -> Value -> Parser a
+typeMismatch expected actual =
+    fail $ "expected " ++ expected ++ ", but encountered " ++ typeOf actual
+
+instance Monad.Monad Parser where
+    m >>= g = Parser $ \path kf ks ->
+      runParser m path kf
+                       (\a -> runParser (g a) path kf ks)
+    return = pure
+
+instance Fail.MonadFail Parser where
+    fail msg = Parser $ \path kf _ks -> kf (reverse path) msg
+
+instance Functor Parser where
+    fmap f m = Parser $ \path kf ks ->
+      let ks' a = ks (f a)
+      in runParser m path kf ks'
+
+instance Applicative Parser where
+    pure a = Parser $ \_path _kf ks -> ks a
+    (<*>) = apP
+
+instance Alternative Parser where
+    empty = fail "empty"
+    (<|>) = mplus
+
+instance MonadPlus Parser where
+    mzero = fail "mzero"
+    mplus a b = Parser $ \path kf ks ->
+      runParser a path (\_ _ -> runParser b path kf ks) ks
+
+instance Semigroup (Parser a) where
+    (<>) = mplus
+
+instance Monoid (Parser a) where
+    mempty  = fail "mempty"
+    mappend = (<>)
+
+apP :: Parser (a -> b) -> Parser a -> Parser b
+apP d e = do
+  b <- d
+  b <$> e
+
+(<?>) :: Parser a -> JSONPathElement -> Parser a
+p <?> pathElem = Parser $ \path kf ks -> runParser p (pathElem:path) kf ks
+
+parseIndexedJSON :: (Value -> Parser a) -> Int -> Value -> Parser a
+parseIndexedJSON p idx value = p value <?> Index idx
+
+unexpected :: Value -> Parser a
+unexpected actual = fail $ "unexpected " ++ typeOf actual
+
+withObject :: String -> (Object -> Parser a) -> Value -> Parser a
+withObject _    f (Object obj) = f obj
+withObject name _ v            = prependContext name (typeMismatch "Object" v)
+
+withArray :: String -> ([Value] -> Parser a) -> Value -> Parser a
+withArray _    f (Array arr) = f arr
+withArray name _ v           = prependContext name (typeMismatch "Array" v)
+
+withString :: String -> (String -> Parser a) -> Value -> Parser a
+withString _    f (String txt) = f txt
+withString name _ v            = prependContext name (typeMismatch "String" v)
+
+withDouble :: String -> (Double -> Parser a) -> Value -> Parser a
+withDouble _    f (Number duble) = f duble
+withDouble name _ v              = prependContext name (typeMismatch "Number" v)
+
+withBool :: String -> (Bool -> Parser a) -> Value -> Parser a
+withBool _    f (Bool arr) = f arr
+withBool name _ v          = prependContext name (typeMismatch "Boolean" v)
+
+class FromJSON a where
+    parseJSON     :: Value -> Parser a
+
+    parseJSONList :: Value -> Parser [a]
+    parseJSONList = withArray "[]" (zipWithM (parseIndexedJSON parseJSON) [0..])
+
+instance FromJSON Bool where
+    parseJSON (Bool b)  = pure b
+    parseJSON v = typeMismatch "Bool" v
+
+instance FromJSON () where
+    parseJSON =
+      withArray "()" $ \v ->
+        if null v
+          then pure ()
+          else prependContext "()" $ fail "expected an empty array"
+
+instance FromJSON Char where
+    parseJSON = withString "Char" parseChar
+
+    parseJSONList (String s) = pure s
+    parseJSONList v = typeMismatch "String" v
+
+parseChar :: String -> Parser Char
+parseChar t =
+    if length t == 1
+      then pure $ head t
+      else prependContext "Char" $ fail "expected a string of length 1"
+
+parseRealFloat :: RealFloat a => String -> Value -> Parser a
+parseRealFloat _    (Number s) = pure $ realToFrac s
+parseRealFloat _    Null       = pure (0/0)
+parseRealFloat name v          = prependContext name (unexpected v)
+
+instance FromJSON Double where
+    parseJSON = parseRealFloat "Double"
+
+instance FromJSON Float where
+    parseJSON = parseRealFloat "Float"
+
+parseNatural :: Integer -> Parser Natural
+parseNatural integer =
+    if integer < 0 then
+        fail $ "parsing Natural failed, unexpected negative number " <> show integer
+    else
+        pure $ fromIntegral integer
+
+parseIntegralFromDouble :: Integral a => Double -> Parser a
+parseIntegralFromDouble d =
+    let r = toRational d
+        x = truncate r
+    in if toRational x == r
+         then pure x
+         else fail $ "unexpected floating number " <> show d
+
+parseIntegral :: Integral a => String -> Value -> Parser a
+parseIntegral name = withDouble name parseIntegralFromDouble
+
+instance FromJSON Integer where
+    parseJSON = parseIntegral "Integer"
+
+instance FromJSON Natural where
+    parseJSON = withDouble "Natural"
+                  (parseIntegralFromDouble >=> parseNatural)
+
+instance FromJSON Int where
+    parseJSON = parseIntegral "Int"
+
+instance FromJSON Int8 where
+    parseJSON = parseIntegral "Int8"
+
+instance FromJSON Int16 where
+    parseJSON = parseIntegral "Int16"
+
+instance FromJSON Int32 where
+    parseJSON = parseIntegral "Int32"
+
+instance FromJSON Int64 where
+    parseJSON = parseIntegral "Int64"
+
+instance FromJSON Word where
+    parseJSON = parseIntegral "Word"
+
+instance FromJSON Word8 where
+    parseJSON = parseIntegral "Word8"
+
+instance FromJSON Word16 where
+    parseJSON = parseIntegral "Word16"
+
+instance FromJSON Word32 where
+    parseJSON = parseIntegral "Word32"
+
+instance FromJSON Word64 where
+    parseJSON = parseIntegral "Word64"
+
+instance FromJSON a => FromJSON [a] where
+    parseJSON = parseJSONList
+
+data Result a = Error String
+              | Success a
+                deriving (Eq, Show)
+
+fromJSON :: FromJSON a => Value -> Result a
+fromJSON = parse parseJSON
+
+parse :: (a -> Parser b) -> a -> Result b
+parse m v = runParser (m v) [] (const Error) Success
+
+parseEither :: (a -> Parser b) -> a -> Either String b
+parseEither m v = runParser (m v) [] onError Right
+  where onError path msg = Left (formatError path msg)
+
+formatError :: JSONPath -> String -> String
+formatError path msg = "Error in " ++ formatPath path ++ ": " ++ msg
+
+formatPath :: JSONPath -> String
+formatPath path = "$" ++ formatRelativePath path
+
+formatRelativePath :: JSONPath -> String
+formatRelativePath path = format "" path
+  where
+    format :: String -> JSONPath -> String
+    format pfx []                = pfx
+    format pfx (Index idx:parts) = format (pfx ++ "[" ++ show idx ++ "]") parts
+    format pfx (Key key:parts)   = format (pfx ++ formatKey key) parts
+
+    formatKey :: String -> String
+    formatKey key
+       | isIdentifierKey key = "." ++ key
+       | otherwise           = "['" ++ escapeKey key ++ "']"
+
+    isIdentifierKey :: String -> Bool
+    isIdentifierKey []     = False
+    isIdentifierKey (x:xs) = isAlpha x && all isAlphaNum xs
+
+    escapeKey :: String -> String
+    escapeKey = concatMap escapeChar
+
+    escapeChar :: Char -> String
+    escapeChar '\'' = "\\'"
+    escapeChar '\\' = "\\\\"
+    escapeChar c    = [c]
+
+explicitParseField :: (Value -> Parser a) -> Object -> String -> Parser a
+explicitParseField p obj key =
+    case key `lookup` obj of
+      Nothing -> fail $ "key " ++ key ++ " not found"
+      Just v  -> p v <?> Key key
+
+(.:) :: FromJSON a => Object -> String -> Parser a
+(.:) = explicitParseField parseJSON
+
+explicitParseFieldMaybe :: (Value -> Parser a) -> Object -> String -> Parser (Maybe a)
+explicitParseFieldMaybe p obj key =
+    case key `lookup` obj of
+      Nothing -> pure Nothing
+      Just v  -> Just <$> p v <?> Key key
+
+(.:?) :: FromJSON a => Object -> String -> Parser (Maybe a)
+(.:?) = explicitParseFieldMaybe parseJSON
+
+
+decodeWith :: (Value -> Result a) -> BSL.ByteString -> Maybe a
+decodeWith decoder bsl =
+   case Parsec.parse parseJSONValue "<input>" bsl of
+     Left  _    -> Nothing
+     Right json ->
+       case decoder json of
+         Success a -> Just a
+         Error _   -> Nothing
+
+decode :: FromJSON a => BSL.ByteString -> Maybe a
+decode = decodeWith fromJSON
+
+eitherDecodeWith :: (Value -> Result a) -> BSL.ByteString -> Either String a
+eitherDecodeWith decoder bsl =
+    case Parsec.parse parseJSONValue "<input>" bsl of
+      Left parsecError -> Left (show parsecError)
+      Right json ->
+        case decoder json of
+          Success a -> Right a
+          Error err -> Left  err
+
+eitherDecode :: FromJSON a => BSL.ByteString -> Either String a
+eitherDecode = eitherDecodeWith fromJSON
+
+
+decodeFile :: FromJSON a => FilePath -> IO (Maybe a)
+decodeFile filePath = do
+    parsecResult <- Parsec.Lazy.parseFromFile parseJSONValue filePath
+    case parsecResult of
+      Right r ->
+        case fromJSON r of
+          Success a -> return (Just a)
+          Error   _ -> return Nothing
+      Left _ -> return Nothing
+
+
+eitherDecodeFile :: FromJSON a => FilePath -> IO (Either String a)
+eitherDecodeFile filePath = do
+    parsecResult <- Parsec.Lazy.parseFromFile parseJSONValue filePath
+    case parsecResult of
+      Right r ->
+        case fromJSON r of
+          Success a -> return (Right a)
+          Error err -> return (Left err)
+      Left err -> return $ Left (show err)
+
diff --git a/src/Haddock/Utils/Json/Parser.hs b/src/Haddock/Utils/Json/Parser.hs
new file mode 100644
--- /dev/null
+++ b/src/Haddock/Utils/Json/Parser.hs
@@ -0,0 +1,102 @@
+-- | Json "Parsec" parser, based on
+-- [json](https://hackage.haskell.org/package/json) package.
+--
+module Haddock.Utils.Json.Parser
+  ( parseJSONValue
+  ) where
+
+import Prelude hiding (null)
+
+import Control.Applicative (Alternative (..))
+import Control.Monad (MonadPlus (..))
+import Data.Char (isHexDigit)
+import Data.Functor (($>))
+import qualified Data.ByteString.Lazy.Char8 as BSCL
+import Numeric
+import Text.Parsec.ByteString.Lazy (Parser)
+import Text.ParserCombinators.Parsec ((<?>))
+import qualified Text.ParserCombinators.Parsec as Parsec
+
+import Haddock.Utils.Json.Types hiding (object)
+
+parseJSONValue :: Parser Value
+parseJSONValue = Parsec.spaces *> parseValue
+
+tok :: Parser a -> Parser a
+tok p = p <* Parsec.spaces
+
+parseValue :: Parser Value
+parseValue =
+         parseNull
+     <|> Bool   <$> parseBoolean
+     <|> Array  <$> parseArray
+     <|> String <$> parseString
+     <|> Object <$> parseObject
+     <|> Number <$> parseNumber
+     <?> "JSON value"
+
+parseNull :: Parser Value
+parseNull = tok
+     $  Parsec.string "null"
+     $> Null
+
+parseBoolean :: Parser Bool
+parseBoolean = tok
+     $  Parsec.string "true"  $> True
+    <|> Parsec.string "false" $> False
+
+parseArray :: Parser [Value]
+parseArray =
+    Parsec.between
+      (tok (Parsec.char '['))
+      (tok (Parsec.char ']'))
+      (parseValue `Parsec.sepBy` tok (Parsec.char ','))
+
+parseString :: Parser String
+parseString =
+    Parsec.between
+      (tok (Parsec.char '"'))
+      (tok (Parsec.char '"'))
+      (many char)
+  where
+    char = (Parsec.char '\\' >> escapedChar)
+       <|> Parsec.satisfy (\x -> x /= '"' && x /= '\\')
+
+    escapedChar =
+          Parsec.char '"'  $> '"'
+      <|> Parsec.char '\\' $> '\\'
+      <|> Parsec.char '/'  $> '/'
+      <|> Parsec.char 'b'  $> '\b'
+      <|> Parsec.char 'f'  $> '\f'
+      <|> Parsec.char 'n'  $> '\n'
+      <|> Parsec.char 'r'  $> '\r'
+      <|> Parsec.char 't'  $> '\t'
+      <|> Parsec.char 'u'  *> uni
+      <?> "escape character"
+
+    uni = check =<< Parsec.count 4 (Parsec.satisfy isHexDigit)
+      where
+        check x | code <= max_char = return (toEnum code)
+                | otherwise        = mzero
+          where code      = fst $ head $ readHex x
+                max_char  = fromEnum (maxBound :: Char)
+
+parseObject :: Parser Object
+parseObject =
+      Parsec.between
+        (tok (Parsec.char '{'))
+        (tok (Parsec.char '}'))
+        (field `Parsec.sepBy` tok (Parsec.char ','))
+  where
+    field :: Parser (String, Value)
+    field = (,)
+        <$> parseString
+        <*  tok (Parsec.char ':')
+        <*> parseValue
+
+parseNumber :: Parser Double
+parseNumber = tok $ do
+  s <- BSCL.unpack <$> Parsec.getInput
+  case readSigned readFloat s of
+    [(n,s')] -> Parsec.setInput (BSCL.pack s') $> n
+    _        -> mzero
diff --git a/src/Haddock/Utils/Json/Types.hs b/src/Haddock/Utils/Json/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/Haddock/Utils/Json/Types.hs
@@ -0,0 +1,42 @@
+module Haddock.Utils.Json.Types
+  ( Value(..)
+  , typeOf
+  , Pair
+  , Object
+  , object
+  ) where
+
+import Data.String
+
+-- TODO: We may want to replace 'String' with 'Text' or 'ByteString'
+
+-- | A JSON value represented as a Haskell value.
+data Value = Object !Object
+           | Array  [Value]
+           | String  String
+           | Number !Double
+           | Bool   !Bool
+           | Null
+           deriving (Eq, Read, Show)
+
+typeOf :: Value -> String
+typeOf v = case v of
+    Object _ -> "Object"
+    Array _  -> "Array"
+    String _ -> "String"
+    Number _ -> "Number"
+    Bool _   -> "Boolean"
+    Null     -> "Null"
+
+-- | A key\/value pair for an 'Object'
+type Pair = (String, Value)
+
+-- | A JSON \"object\" (key/value map).
+type Object = [Pair]
+
+-- | Create a 'Value' from a list of name\/value 'Pair's.
+object :: [Pair] -> Value
+object = Object
+
+instance IsString Value where
+  fromString = String
