diff options
Diffstat (limited to 'haddock-api')
33 files changed, 1382 insertions, 785 deletions
| diff --git a/haddock-api/haddock-api.cabal b/haddock-api/haddock-api.cabal index 0aac70e5..3e972877 100644 --- a/haddock-api/haddock-api.cabal +++ b/haddock-api/haddock-api.cabal @@ -1,5 +1,6 @@ +cabal-version:        2.0  name:                 haddock-api -version:              2.18.2 +version:              2.20.0  synopsis:             A documentation-generation tool for Haskell libraries  description:          Haddock is a documentation-generation tool for Haskell                        libraries @@ -12,7 +13,6 @@ bug-reports:          https://github.com/haskell/haddock/issues  copyright:            (c) Simon Marlow, David Waern  category:             Documentation  build-type:           Simple -cabal-version:        >= 2.0  extra-source-files:    CHANGES.md @@ -41,10 +41,10 @@ library    -- this package typically supports only single major versions    build-depends: base            ^>= 4.12.0 -               , Cabal           ^>= 2.0.0 -               , ghc             ^>= 8.3 +               , Cabal           ^>= 2.3.0 +               , ghc             ^>= 8.5                 , ghc-paths       ^>= 0.1.0.9 -               , haddock-library ^>= 1.4.6 +               , haddock-library ^>= 1.6.0                 , xhtml           ^>= 3000.2.2    -- Versions for the dependencies below are transitively pinned by @@ -124,27 +124,71 @@ test-suite spec        test      , src -  -- NB: We only use a small subset of lib:haddock-api here, which -  --     explains why this component has a smaller build-depends set    other-modules: +    Haddock +    Haddock.Backends.Hoogle +    Haddock.Backends.Hyperlinker +    Haddock.Backends.Hyperlinker.Ast +    Haddock.Backends.Hyperlinker.Renderer +    Haddock.Backends.Hyperlinker.Utils +    Haddock.Backends.LaTeX +    Haddock.Backends.Xhtml +    Haddock.Backends.Xhtml.Decl +    Haddock.Backends.Xhtml.DocMarkup +    Haddock.Backends.Xhtml.Layout +    Haddock.Backends.Xhtml.Meta +    Haddock.Backends.Xhtml.Names +    Haddock.Backends.Xhtml.Themes +    Haddock.Backends.Xhtml.Types +    Haddock.Backends.Xhtml.Utils +    Haddock.Convert +    Haddock.Doc +    Haddock.GhcUtils +    Haddock.Interface +    Haddock.Interface.AttachInstances +    Haddock.Interface.Create +    Haddock.Interface.Json +    Haddock.Interface.LexParseRn +    Haddock.Interface.ParseModuleHeader +    Haddock.Interface.Rename +    Haddock.Interface.Specialize +    Haddock.InterfaceFile +    Haddock.ModuleTree +    Haddock.Options +    Haddock.Parser +    Haddock.Syb +    Haddock.Types +    Haddock.Utils +    Haddock.Utils.Json +    Haddock.Version +    Paths_haddock_api      Haddock.Backends.Hyperlinker.ParserSpec      Haddock.Backends.Hyperlinker.Parser      Haddock.Backends.Hyperlinker.Types -  build-depends: -      ghc         ^>= 8.3 -    , hspec       ^>= 2.4.4 -    , QuickCheck  ^>= 2.10 +  build-depends: Cabal           ^>= 2.3 +               , ghc             ^>= 8.4 +               , ghc-paths       ^>= 0.1.0.9 +               , haddock-library ^>= 1.6.0 +               , xhtml           ^>= 3000.2.2 +               , hspec           >= 2.4.4 && < 2.6 +               , QuickCheck      ^>= 2.11    -- Versions for the dependencies below are transitively pinned by    -- the non-reinstallable `ghc` package and hence need no version    -- bounds -  build-depends: -      base -    , containers +  build-depends: base +               , array +               , bytestring +               , containers +               , deepseq +               , directory +               , filepath +               , ghc-boot +               , transformers    build-tool-depends: -    hspec-discover:hspec-discover ^>= 2.4.4 +    hspec-discover:hspec-discover >= 2.4.4 && < 2.6  source-repository head    type:     git diff --git a/haddock-api/resources/html/Classic.theme/xhaddock.css b/haddock-api/resources/html/Classic.theme/xhaddock.css index 1bf668e9..b8164815 100644 --- a/haddock-api/resources/html/Classic.theme/xhaddock.css +++ b/haddock-api/resources/html/Classic.theme/xhaddock.css @@ -392,6 +392,20 @@ td.rdoc p {  } +.doc table { +  border-collapse: collapse; +  border-spacing: 0px; +} + +.doc th, +.doc td { +  padding: 5px; +  border: 1px solid #ddd; +} + +.doc th { +  background-color: #f0f0f0; +}  #footer {    background-color: #000099; diff --git a/haddock-api/resources/html/Ocean.std-theme/ocean.css b/haddock-api/resources/html/Ocean.std-theme/ocean.css index 0852dea5..ba6af9ca 100644 --- a/haddock-api/resources/html/Ocean.std-theme/ocean.css +++ b/haddock-api/resources/html/Ocean.std-theme/ocean.css @@ -443,6 +443,21 @@ div#style-menu-holder {    margin-top: 0.8em;  } +.doc table { +  border-collapse: collapse; +  border-spacing: 0px; +} + +.doc th, +.doc td { +  padding: 5px; +  border: 1px solid #ddd; +} + +.doc th { +  background-color: #f0f0f0; +} +  .clearfix:after {    clear: both;    content: " "; diff --git a/haddock-api/resources/html/haddock-bundle.min.js b/haddock-api/resources/html/haddock-bundle.min.js index 82a34ddb..1061714b 100644 --- a/haddock-api/resources/html/haddock-bundle.min.js +++ b/haddock-api/resources/html/haddock-bundle.min.js @@ -1,2 +1,2 @@ -!function e(t,n,o){function r(s,a){if(!n[s]){if(!t[s]){var l="function"==typeof require&&require;if(!a&&l)return l(s,!0);if(i)return i(s,!0);var c=new Error("Cannot find module '"+s+"'");throw c.code="MODULE_NOT_FOUND",c}var u=n[s]={exports:{}};t[s][0].call(u.exports,function(e){var n=t[s][1][e];return r(n||e)},u,u.exports,e,t,n,o)}return n[s].exports}for(var i="function"==typeof require&&require,s=0;s<o.length;s++)r(o[s]);return r}({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";function o(e){var t=d[e];if(void 0==t)throw new Error("could not find <details> element with id '"+e+"'");return t}function r(e){for(var t=e.target,n=t.id,r=o(n),i=r.element.open,s=0,l=r.toggles;s<l.length;s++){var c=l[s];c.classList.contains("details-toggle-control")&&(c.classList.add(i?"collapser":"expander"),c.classList.remove(i?"expander":"collapser"))}t.open==r.openByDefault?delete p[n]:p[n]=!0,a()}function i(){for(var e=0,t=Array.prototype.slice.call(document.getElementsByTagName("details"));e<t.length;e++){var n=t[e];"string"==typeof n.id&&n.id.length>0&&(d[n.id]={element:n,openByDefault:!!n.open,toggles:[]},n.addEventListener("toggle",r))}}function s(e){var t=o(e).element;t.open=!t.open}function a(){var e=Object.keys(p);document.cookie="toggled="+encodeURIComponent(e.join("+"))}function l(){var e=h.getCookie("toggled");if(e)for(var t=0,n=e.split("+");t<n.length;t++){var o=n[t],r=d[o];p[o]=!0,r&&(r.element.open=!r.element.open)}}function c(e){e.preventDefault();var t=e.currentTarget.getAttribute("data-details-id");if(!t)throw new Error("element with class 'details-toggle' has no 'data-details-id' attribute!");s(t)}function u(){Array.prototype.slice.call(document.getElementsByClassName("details-toggle")).forEach(function(e){var t=e.getAttribute("data-details-id");if(!t)throw new Error("element with class 'details-toggle' has no 'data-details-id' attribute!");var n=o(t);n.toggles.push(e),e.addEventListener("click",c),e.classList.contains("details-toggle-control")&&e.classList.add(n.element.open?"collapser":"expander")})}Object.defineProperty(n,"__esModule",{value:!0});var h=e("./cookies"),d={},p={};n.init=function(){i(),l(),u()}},{"./cookies":1}],3:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var o=e("./style-menu"),r=e("./details-helper"),i=e("./quick-jump");!function(e){"interactive"===document.readyState?e():document.addEventListener("readystatechange",function(){"interactive"===document.readyState&&e()})}(function(){document.body.classList.add("js-enabled"),o.init(),r.init(),i.init()})},{"./details-helper":2,"./quick-jump":4,"./style-menu":5}],4:[function(e,t,n){"use strict";function o(e,t,n){var o=new XMLHttpRequest;o.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()}function r(e){var t=document.querySelector("#page-menu"),n=document.createElement("li");t.insertBefore(n,t.firstChild),d.render(p(v,{onClick:e,title:"Quick Jump"}),t,n)}function i(e,t){return t.length<=e?t:t.slice(0,e)}function s(){return p("table",{class:"keyboard-shortcuts"},p("tr",null,p("th",null,"Key"),p("th",null,"Shortcut")),p("tr",null,p("td",null,p("span",{class:"key"},"s")),p("td",null,"Open this search box")),p("tr",null,p("td",null,p("span",{class:"key"},"esc")),p("td",null,"Close this search box")),p("tr",null,p("td",null,p("span",{class:"key"},"↓"),",",p("span",{class:"key"},"ctrl")," + ",p("span",{class:"key"},"j")),p("td",null,"Move down in search results")),p("tr",null,p("td",null,p("span",{class:"key"},"↑"),",",p("span",{class:"key"},"ctrl")," + ",p("span",{class:"key"},"k")),p("td",null,"Move up in search results")),p("tr",null,p("td",null,p("span",{class:"key"},"↵")),p("td",null,"Go to active search result")))}function a(){return p("p",null,"You can find any exported type, constructor, class, function or pattern defined in this package by (approximate) name.")}function l(e){var t=[p("p",null,"Your search for '",e.searchString,"' produced the following list of results: ",p("code",null,"[]"),"."),p("p",null,p("code",null,"Nothing")," matches your query for '",e.searchString,"'."),p("p",null,p("code",null,"Left \"no matches for '",e.searchString,"'\" :: Either String (NonEmpty SearchResult)"))];return t[(e.searchString||"a").charCodeAt(0)%t.length]}function c(e,t){d.render(p(g,{baseUrl:e||".",showHideTrigger:t||r}),document.body)}var u=this&&this.__extends||function(){var e=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])};return function(t,n){function o(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(o.prototype=n.prototype,new o)}}();Object.defineProperty(n,"__esModule",{value:!0});var h=e("fuse.js"),d=e("preact"),p=d.h,f=d.Component,v=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return u(t,e),t.prototype.render=function(e){return p("li",null,p("a",{href:"#",onClick:function(t){t.preventDefault(),e.onClick()}},e.title))},t}(f),g=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.linkIndex=0,t.focusPlease=!1,t.navigatedByKeyboard=!1,t}return u(t,e),t.prototype.componentWillMount=function(){var e=this;this.setState({searchString:"",isVisible:!1,expanded:{},activeLinkIndex:-1,moduleResults:[]}),o(this.props.baseUrl+"/doc-index.json",function(t){e.setState({fuse:new h(t,{threshold:.25,caseSensitive:!0,includeScore:!0,tokenize:!0,keys:["name","module"]}),moduleResults:[]})},function(t){console&&console.error("could not load 'doc-index.json' for searching",t),e.setState({failedLoading:!0})}),document.addEventListener("mousedown",this.hide.bind(this)),document.addEventListener("keydown",function(t){e.state.isVisible&&("Escape"===t.key?e.hide():"ArrowUp"===t.key||"k"===t.key&&t.ctrlKey?(t.preventDefault(),e.navigateLinks(-1)):"ArrowDown"===t.key||"j"===t.key&&t.ctrlKey?(t.preventDefault(),e.navigateLinks(1)):"Enter"===t.key&&e.state.activeLinkIndex>=0&&e.followActiveLink()),"s"===t.key&&"input"!==t.target.tagName.toLowerCase()&&(t.preventDefault(),e.show())})},t.prototype.hide=function(){this.setState({isVisible:!1})},t.prototype.show=function(){this.state.isVisible||(this.focusPlease=!0,this.setState({isVisible:!0,activeLinkIndex:-1}))},t.prototype.toggleVisibility=function(){this.state.isVisible?this.hide():this.show()},t.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})},t.prototype.followActiveLink=function(){this.activeLinkAction&&this.activeLinkAction()},t.prototype.updateResults=function(){var e=this.input&&this.input.value||"",t={};this.state.fuse.search(e).forEach(function(e){var n=e.item.module;(t[n]||(t[n]=[])).push(e)});var n=[];for(var o in t)!function(e){var o=t[e],r=0;o.forEach(function(e){r+=1/e.score}),n.push({module:e,totalScore:1/r,items:o})}(o);n.sort(function(e,t){return e.totalScore-t.totalScore}),this.setState({searchString:e,isVisible:!0,moduleResults:n})},t.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},t.prototype.componentDidMount=function(){this.props.showHideTrigger(this.toggleVisibility.bind(this))},t.prototype.render=function(e,t){var n=this;if(t.failedLoading){var o="file:"==window.location.protocol;return p("div",{id:"search",class:t.isVisible?"":"hidden"},p("div",{id:"search-results"},p("p",{class:"error"},"Failed to load file 'doc-index.json' containing definitions in this package."),o?p("p",{class:"error"},"To use quick jump, load this page with HTTP (from a local static file web server) instead of using the ",p("code",null,"file://")," protocol. (For security reasons, it is not possible to fetch auxiliary files using JS in a HTML page opened with ",p("code",null,"file://"),".)"):[]))}this.linkIndex=0;var r=function(e){e.stopPropagation()},c=i(10,t.moduleResults).map(function(e){return n.renderResultsInModule(e)});return p("div",{id:"search",class:t.isVisible?"":"hidden"},p("div",{id:"search-form",onMouseDown:r},p("input",{placeholder:"Search in package by name",ref:function(e){n.input=e},onFocus:this.show.bind(this),onClick:this.show.bind(this),onInput:this.updateResults.bind(this)})),p("div",{id:"search-results",ref:function(e){n.searchResults=e},onMouseDown:r,onMouseOver:function(e){for(var t=e.target;t&&"function"==typeof t.getAttribute;){var o=t.getAttribute("data-link-index");if("string"==typeof o){var r=parseInt(o,10);n.setState({activeLinkIndex:r});break}t=t.parentNode}}},""===t.searchString?[p(a,null),p(s,null)]:0==c.length?p(l,{searchString:t.searchString}):p("ul",null,c)))},t.prototype.renderResultsInModule=function(e){var t=this,n=e.items,o=e.module,r=this.state.expanded[o]||n.length<=10,s=r?n:i(8,n),a=function(e){return p("li",{class:"search-result"},t.navigationLink(t.props.baseUrl+"/"+e.link,{},p(m,{html:e.display_html})))};return p("li",{class:"search-module"},p("h4",null,o),p("ul",null,s.map(function(e){return a(e.item)}),r?[]:p("li",{class:"more-results"},this.actionLink(function(){var e=Object.assign({},t.state.expanded);e[o]=!0,t.setState({expanded:e})},{},"show "+(n.length-s.length)+" more results from this module"))))},t.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),s=function(){window.location.href=e,n.hide()};return this.menuLink.apply(this,[i,s].concat(o))},t.prototype.actionLink=function(e,t){for(var n=[],o=2;o<arguments.length;o++)n[o-2]=arguments[o];var r=Object.assign({href:"#",onClick:function(t){t.preventDefault(),e()}},t);return this.menuLink.apply(this,[r,e].concat(n))},t.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,p.apply(void 0,["a",s].concat(o))},t}(f),m=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return u(t,e),t.prototype.shouldComponentUpdate=function(e){return this.props.html!==e.html},t.prototype.render=function(e){return p("div",{dangerouslySetInnerHTML:{__html:e.html}})},t}(f);n.init=c,window.quickNav={init:c}},{"fuse.js":6,preact:7}],5:[function(e,t,n){"use strict";function o(e){return(" "+e+" ").replace(g," ")}function r(e){return e.replace(m,"")}function i(e,t){return o(e.className||"").indexOf(" "+t+" ")>=0}function s(e,t){var n=o(e.className||"");n.indexOf(" "+t+" ")<0&&(e.className=r(n+" "+t))}function a(e,t){var n=o(e.className||"");n=n.replace(" "+t+" "," "),e.className=r(n)}function l(e,t,n,o){return null==o&&(o=!i(e,t)),o?(a(e,n),s(e,t)):(a(e,t),s(e,n)),o}function c(e){var t=document.getElementById("page-menu");if(t&&t.firstChild){var n=t.firstChild.cloneNode(!1);n.innerHTML=e,t.appendChild(n)}}function u(){return Array.prototype.slice.call(document.getElementsByTagName("link")).filter(function(e){return-1!=e.rel.indexOf("style")&&e.title})}function h(){var e=u(),t="";e.forEach(function(e){t+="<li><a href='#' onclick=\"setActiveStyleSheet('"+e.title+"'); return false;\">"+e.title+"</a></li>"}),e.length>1&&c("<div id='style-menu-holder'><a href='#' onclick='styleMenu(); return false;'>Style ▾</a><ul id='style-menu' class='hide'>"+t+"</ul></div>")}function d(e){for(var t=u(),n=null,o=0;o<t.length;o++){var r=t[o];r.disabled=!0,r.title==e&&(n=r)}n?(n.disabled=!1,v.setCookie("haddock-style",e)):(t[0].disabled=!1,v.clearCookie("haddock-style")),f(!1)}function p(){var e=v.getCookie("haddock-style");e&&d(e)}function f(e){var t=document.getElementById("style-menu");t&&y(t,e)}Object.defineProperty(n,"__esModule",{value:!0});var v=e("./cookies"),g=/\s\s+/g,m=/^\s+|\s+$/g,y=function(e,t){return function(n,o){return l(n,e,t,o)}}("show","hide");n.init=function(){h(),p()}},{"./cookies":1}],6:[function(e,t,n){!function(e,o){"object"==typeof n&&"object"==typeof t?t.exports=o():"function"==typeof define&&define.amd?define("Fuse",[],o):"object"==typeof n?n.Fuse=o():e.Fuse=o()}(this,function(){return function(e){function t(o){if(n[o])return n[o].exports;var r=n[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,t),r.l=!0,r.exports}var n={};return t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,o){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:o})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=8)}([function(e,t,n){"use strict";e.exports=function(e){return"[object Array]"===Object.prototype.toString.call(e)}},function(e,t,n){"use strict";function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var r=function(){function e(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(t,n,o){return n&&e(t.prototype,n),o&&e(t,o),t}}(),i=n(5),s=n(7),a=n(4),l=function(){function e(t,n){var r=n.location,i=void 0===r?0:r,s=n.distance,l=void 0===s?100:s,c=n.threshold,u=void 0===c?.6:c,h=n.maxPatternLength,d=void 0===h?32:h,p=n.isCaseSensitive,f=void 0!==p&&p,v=n.tokenSeparator,g=void 0===v?/ +/g:v,m=n.findAllMatches,y=void 0!==m&&m,_=n.minMatchCharLength,k=void 0===_?1:_;o(this,e),this.options={location:i,distance:l,threshold:u,maxPatternLength:d,isCaseSensitive:f,tokenSeparator:g,findAllMatches:y,minMatchCharLength:k},this.pattern=this.options.isCaseSensitive?t:t.toLowerCase(),this.pattern.length<=d&&(this.patternAlphabet=a(this.pattern))}return r(e,[{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 i(e,this.pattern,o);var r=this.options,a=r.location,l=r.distance,c=r.threshold,u=r.findAllMatches,h=r.minMatchCharLength;return s(e,this.pattern,this.patternAlphabet,{location:a,distance:l,threshold:c,findAllMatches:u,minMatchCharLength:h})}}]),e}();e.exports=l},function(e,t,n){"use strict";var o=n(0),r=function e(t,n,r){if(n){var i=n.indexOf("."),s=n,a=null;-1!==i&&(s=n.slice(0,i),a=n.slice(i+1));var l=t[s];if(null!==l&&void 0!==l)if(a||"string"!=typeof l&&"number"!=typeof l)if(o(l))for(var c=0,u=l.length;c<u;c+=1)e(l[c],a,r);else a&&e(l,a,r);else r.push(l.toString())}else r.push(t);return r};e.exports=function(e,t){return r(e,t,[])}},function(e,t,n){"use strict";e.exports=function(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1&&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||((r=i-1)-o+1>=t&&n.push([o,r]),o=-1)}return e[i-1]&&i-o>=t&&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 o=/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g;e.exports=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:/ +/g,r=new RegExp(t.replace(o,"\\$&").replace(n,"|")),i=e.match(r),s=!!i,a=[];if(s)for(var l=0,c=i.length;l<c;l+=1){var u=i[l];a.push([e.indexOf(u),u.length-1])}return{score:s?.5:1,isMatch:s,matchedIndices:a}}},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 o=n(6),r=n(3);e.exports=function(e,t,n,i){for(var s=i.location,a=void 0===s?0:s,l=i.distance,c=void 0===l?100:l,u=i.threshold,h=void 0===u?.6:u,d=i.findAllMatches,p=void 0!==d&&d,f=i.minMatchCharLength,v=void 0===f?1:f,g=a,m=e.length,y=h,_=e.indexOf(t,g),k=t.length,b=[],x=0;x<m;x+=1)b[x]=0;if(-1!==_){var w=o(t,{errors:0,currentLocation:_,expectedLocation:g,distance:c});if(y=Math.min(w,y),-1!==(_=e.lastIndexOf(t,g+k))){var S=o(t,{errors:0,currentLocation:_,expectedLocation:g,distance:c});y=Math.min(S,y)}}_=-1;for(var L=[],C=1,M=k+m,N=1<<k-1,I=0;I<k;I+=1){for(var A=0,O=M;A<O;)o(t,{errors:I,currentLocation:g+O,expectedLocation:g,distance:c})<=y?A=O:M=O,O=Math.floor((M-A)/2+A);M=O;var E=Math.max(1,g-O+1),T=p?m:Math.min(g+O,m)+k,j=Array(T+2);j[T+1]=(1<<I)-1;for(var P=T;P>=E;P-=1){var R=P-1,U=n[e.charAt(R)];if(U&&(b[R]=1),j[P]=(j[P+1]<<1|1)&U,0!==I&&(j[P]|=(L[P+1]|L[P])<<1|1|L[P+1]),j[P]&N&&(C=o(t,{errors:I,currentLocation:R,expectedLocation:g,distance:c}))<=y){if(y=C,(_=R)<=g)break;E=Math.max(1,2*g-_)}}if(o(t,{errors:I+1,currentLocation:g,expectedLocation:g,distance:c})>y)break;L=j}return{isMatch:_>=0,score:0===C?.001:C,matchedIndices:r(b,v)}}},function(e,t,n){"use strict";function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var r=function(){function e(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(t,n,o){return n&&e(t.prototype,n),o&&e(t,o),t}}(),i=n(1),s=n(2),a=n(0),l=function(){function e(t,n){var r=n.location,i=void 0===r?0:r,a=n.distance,l=void 0===a?100:a,c=n.threshold,u=void 0===c?.6:c,h=n.maxPatternLength,d=void 0===h?32:h,p=n.caseSensitive,f=void 0!==p&&p,v=n.tokenSeparator,g=void 0===v?/ +/g:v,m=n.findAllMatches,y=void 0!==m&&m,_=n.minMatchCharLength,k=void 0===_?1:_,b=n.id,x=void 0===b?null:b,w=n.keys,S=void 0===w?[]:w,L=n.shouldSort,C=void 0===L||L,M=n.getFn,N=void 0===M?s:M,I=n.sortFn,A=void 0===I?function(e,t){return e.score-t.score}:I,O=n.tokenize,E=void 0!==O&&O,T=n.matchAllTokens,j=void 0!==T&&T,P=n.includeMatches,R=void 0!==P&&P,U=n.includeScore,D=void 0!==U&&U,V=n.verbose,F=void 0!==V&&V;o(this,e),this.options={location:i,distance:l,threshold:u,maxPatternLength:d,isCaseSensitive:f,tokenSeparator:g,findAllMatches:y,minMatchCharLength:k,id:x,keys:S,includeMatches:R,includeScore:D,shouldSort:C,getFn:N,sortFn:A,verbose:F,tokenize:E,matchAllTokens:j},this.setCollection(t)}return r(e,[{key:"setCollection",value:function(e){return this.list=e,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=arguments.length>0&&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=arguments.length>0&&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,d=this.options.keys.length;h<d;h+=1){var p=this.options.keys[h];if("string"!=typeof p){if(a[p.name]={weight:1-p.weight||1},p.weight<=0||p.weight>1)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,l=e.index,c=t.tokenSearchers,u=void 0===c?[]:c,h=t.fullSearcher,d=void 0===h?[]:h,p=t.resultMap,f=void 0===p?{}:p,v=t.results,g=void 0===v?[]:v;if(void 0!==i&&null!==i){var m=!1,y=-1,_=0;if("string"==typeof i){this._log("\nKey: "+(""===n?"-":n));var k=d.search(i);if(this._log('Full text: "'+i+'", score: '+k.score),this.options.tokenize){for(var b=i.split(this.options.tokenSeparator),x=[],w=0;w<u.length;w+=1){var S=u[w];this._log('\nPattern: "'+S.pattern+'"');for(var L=!1,C=0;C<b.length;C+=1){var M=b[C],N=S.search(M),I={};N.isMatch?(I[M]=N.score,m=!0,L=!0,x.push(N.score)):(I[M]=1,this.options.matchAllTokens||x.push(1)),this._log('Token: "'+M+'", score: '+I[M])}L&&(_+=1)}y=x[0];for(var A=x.length,O=1;O<A;O+=1)y+=x[O];y/=A,this._log("Token score average:",y)}var E=k.score;y>-1&&(E=(E+y)/2),this._log("Score average:",E);var T=!this.options.tokenize||!this.options.matchAllTokens||_>=u.length;if(this._log("\nCheck Matches: "+T),(m||k.isMatch)&&T){var j=f[l];j?j.output.push({key:n,arrayIndex:r,value:i,score:E,matchedIndices:k.matchedIndices}):(f[l]={item:s,output:[{key:n,arrayIndex:r,value:i,score:E,matchedIndices:k.matchedIndices}]},g.push(f[l]))}}else if(a(i))for(var P=0,R=i.length;P<R;P+=1)this._analyze({key:n,arrayIndex:P,value:i[P],record:s,index:l},{resultMap:f,results:g,tokenSearchers:u,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=0,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):(r[l].nScore=u,s+=u)}t[n].score=1===a?s/i: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._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")&&i.arrayIndex>-1&&(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(){if(this.options.verbose){var e;(e=console).log.apply(e,arguments)}}}]),e}();e.exports=l}])})},{}],7:[function(e,t,n){!function(){"use strict";function e(){}function n(t,n){var o,r,i,s,a=O;for(s=arguments.length;s-- >2;)A.push(arguments[s]);for(n&&null!=n.children&&(A.length||A.push(n.children),delete n.children);A.length;)if((r=A.pop())&&void 0!==r.pop)for(s=r.length;s--;)A.push(r[s]);else"boolean"==typeof r&&(r=null),(i="function"!=typeof t)&&(null==r?r="":"number"==typeof r?r=String(r):"string"!=typeof r&&(i=!1)),i&&o?a[a.length-1]+=r:a===O?a=[r]:a.push(r),o=i;var l=new e;return l.nodeName=t,l.children=a,l.attributes=null==n?void 0:n,l.key=null==n?void 0:n.key,void 0!==I.vnode&&I.vnode(l),l}function o(e,t){for(var n in t)e[n]=t[n];return e}function r(e){!e.__d&&(e.__d=!0)&&1==j.push(e)&&(I.debounceRendering||E)(i)}function i(){var e,t=j;for(j=[];e=t.pop();)e.__d&&L(e)}function s(e,t,n){return"string"==typeof t||"number"==typeof t?void 0!==e.splitText:"string"==typeof t.nodeName?!e._componentConstructor&&a(e,t.nodeName):n||e._componentConstructor===t.nodeName}function a(e,t){return e.__n===t||e.nodeName.toLowerCase()===t.toLowerCase()}function l(e){var t=o({},e.attributes);t.children=e.children;var n=e.nodeName.defaultProps;if(void 0!==n)for(var r in n)void 0===t[r]&&(t[r]=n[r]);return t}function c(e,t){var n=t?document.createElementNS("http://www.w3.org/2000/svg",e):document.createElement(e);return n.__n=e,n}function u(e){var t=e.parentNode;t&&t.removeChild(e)}function h(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===T.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,p,s):e.removeEventListener(t,p,s),(e.__l||(e.__l={}))[t]=o}else if("list"!==t&&"type"!==t&&!r&&t in e)d(e,t,null==o?"":o),null!=o&&!1!==o||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 d(e,t,n){try{e[t]=n}catch(e){}}function p(e){return this.__l[e.type](I.event&&I.event(e)||e)}function f(){for(var e;e=P.pop();)I.afterMount&&I.afterMount(e),e.componentDidMount&&e.componentDidMount()}function v(e,t,n,o,r,i){R++||(U=null!=r&&void 0!==r.ownerSVGElement,D=null!=e&&!("__preactattr_"in e));var s=g(e,t,n,o,i);return r&&s.parentNode!==r&&r.appendChild(s),--R||(D=!1,i||f()),s}function g(e,t,n,o,r){var i=e,s=U;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),y(e,!0))),i.__preactattr_=!0,i;var l=t.nodeName;if("function"==typeof l)return C(e,t,n,o);if(U="svg"===l||"foreignObject"!==l&&U,l=String(l),(!e||!a(e,l))&&(i=c(l,U),e)){for(;e.firstChild;)i.appendChild(e.firstChild);e.parentNode&&e.parentNode.replaceChild(i,e),y(e,!0)}var u=i.firstChild,h=i.__preactattr_,d=t.children;if(null==h){h=i.__preactattr_={};for(var p=i.attributes,f=p.length;f--;)h[p[f].name]=p[f].value}return!D&&d&&1===d.length&&"string"==typeof d[0]&&null!=u&&void 0!==u.splitText&&null==u.nextSibling?u.nodeValue!=d[0]&&(u.nodeValue=d[0]):(d&&d.length||null!=u)&&m(i,d,n,o,D||null!=h.dangerouslySetInnerHTML),k(i,t.attributes,h),U=s,i}function m(e,t,n,o,r){var i,a,l,c,h,d=e.childNodes,p=[],f={},v=0,m=0,_=d.length,k=0,b=t?t.length:0;if(0!==_)for(L=0;L<_;L++){var x=d[L],w=x.__preactattr_;null!=(S=b&&w?x._component?x._component.__k:w.key:null)?(v++,f[S]=x):(w||(void 0!==x.splitText?!r||x.nodeValue.trim():r))&&(p[k++]=x)}if(0!==b)for(L=0;L<b;L++){h=null;var S=(c=t[L]).key;if(null!=S)v&&void 0!==f[S]&&(h=f[S],f[S]=void 0,v--);else if(!h&&m<k)for(i=m;i<k;i++)if(void 0!==p[i]&&s(a=p[i],c,r)){h=a,p[i]=void 0,i===k-1&&k--,i===m&&m++;break}h=g(h,c,n,o),l=d[L],h&&h!==e&&h!==l&&(null==l?e.appendChild(h):h===l.nextSibling?u(l):e.insertBefore(h,l))}if(v)for(var L in f)void 0!==f[L]&&y(f[L],!1);for(;m<=k;)void 0!==(h=p[k--])&&y(h,!1)}function y(e,t){var n=e._component;n?M(n):(null!=e.__preactattr_&&e.__preactattr_.ref&&e.__preactattr_.ref(null),!1!==t&&null!=e.__preactattr_||u(e),_(e))}function _(e){for(e=e.lastChild;e;){var t=e.previousSibling;y(e,!0),e=t}}function k(e,t,n){var o;for(o in n)t&&null!=t[o]||null==n[o]||h(e,o,n[o],n[o]=void 0,U);for(o in t)"children"===o||"innerHTML"===o||o in n&&t[o]===("value"===o||"checked"===o?e[o]:n[o])||h(e,o,n[o],n[o]=t[o],U)}function b(e){var t=e.constructor.name;(V[t]||(V[t]=[])).push(e)}function x(e,t,n){var o,r=V[e.name];if(e.prototype&&e.prototype.render?(o=new e(t,n),N.call(o,t,n)):((o=new N(t,n)).constructor=e,o.render=w),r)for(var i=r.length;i--;)if(r[i].constructor===e){o.__b=r[i].__b,r.splice(i,1);break}return o}function w(e,t,n){return this.constructor(e,n)}function S(e,t,n,o,i){e.__x||(e.__x=!0,(e.__r=t.ref)&&delete t.ref,(e.__k=t.key)&&delete t.key,!e.base||i?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===I.syncComponentUpdates&&e.base?r(e):L(e,1,i)),e.__r&&e.__r(e))}function L(e,t,n,r){if(!e.__x){var i,s,a,c=e.props,u=e.state,h=e.context,d=e.__p||c,p=e.__s||u,g=e.__c||h,m=e.base,_=e.__b,k=m||_,b=e._component,w=!1;if(m&&(e.props=d,e.state=p,e.context=g,2!==t&&e.shouldComponentUpdate&&!1===e.shouldComponentUpdate(c,u,h)?w=!0:e.componentWillUpdate&&e.componentWillUpdate(c,u,h),e.props=c,e.state=u,e.context=h),e.__p=e.__s=e.__c=e.__b=null,e.__d=!1,!w){i=e.render(c,u,h),e.getChildContext&&(h=o(o({},h),e.getChildContext()));var C,N,A=i&&i.nodeName;if("function"==typeof A){var O=l(i);(s=b)&&s.constructor===A&&O.key==s.__k?S(s,O,1,h,!1):(C=s,e._component=s=x(A,O,h),s.__b=s.__b||_,s.__u=e,S(s,O,0,h,!1),L(s,1,n,!0)),N=s.base}else a=k,(C=b)&&(a=e._component=null),(k||1===t)&&(a&&(a._component=null),N=v(a,i,h,n||!m,k&&k.parentNode,!0));if(k&&N!==k&&s!==b){var E=k.parentNode;E&&N!==E&&(E.replaceChild(N,k),C||(k._component=null,y(k,!1)))}if(C&&M(C),e.base=N,N&&!r){for(var T=e,j=e;j=j.__u;)(T=j).base=N;N._component=T,N._componentConstructor=T.constructor}}if(!m||n?P.unshift(e):w||(e.componentDidUpdate&&e.componentDidUpdate(d,p,g),I.afterUpdate&&I.afterUpdate(e)),null!=e.__h)for(;e.__h.length;)e.__h.pop().call(e);R||r||f()}}function C(e,t,n,o){for(var r=e&&e._component,i=r,s=e,a=r&&e._componentConstructor===t.nodeName,c=a,u=l(t);r&&!c&&(r=r.__u);)c=r.constructor===t.nodeName;return r&&c&&(!o||r._component)?(S(r,u,3,n,o),e=r.base):(i&&!a&&(M(i),e=s=null),r=x(t.nodeName,u,n),e&&!r.__b&&(r.__b=e,s=null),S(r,u,1,n,o),e=r.base,s&&e!==s&&(s._component=null,y(s,!1))),e}function M(e){I.beforeUnmount&&I.beforeUnmount(e);var t=e.base;e.__x=!0,e.componentWillUnmount&&e.componentWillUnmount(),e.base=null;var n=e._component;n?M(n):t&&(t.__preactattr_&&t.__preactattr_.ref&&t.__preactattr_.ref(null),e.__b=t,u(t),b(e),_(t)),e.__r&&e.__r(null)}function N(e,t){this.__d=!0,this.context=t,this.props=e,this.state=this.state||{}}var I={},A=[],O=[],E="function"==typeof Promise?Promise.resolve().then.bind(Promise.resolve()):setTimeout,T=/acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i,j=[],P=[],R=0,U=!1,D=!1,V={};o(N.prototype,{setState:function(e,t){var n=this.state;this.__s||(this.__s=o({},n)),o(n,"function"==typeof e?e(n,this.props):e),t&&(this.__h=this.__h||[]).push(t),r(this)},forceUpdate:function(e){e&&(this.__h=this.__h||[]).push(e),L(this,2)},render:function(){}});var F={h:n,createElement:n,cloneElement:function(e,t){return n(e.nodeName,o(o({},e.attributes),t),arguments.length>2?[].slice.call(arguments,2):e.children)},Component:N,render:function(e,t,n){return v(n,e,{},!1,t,!1)},rerender:i,options:I};void 0!==t?t.exports=F:self.preact=F}()},{}]},{},[3]); +!function e(t,n,o){function r(s,a){if(!n[s]){if(!t[s]){var l="function"==typeof require&&require;if(!a&&l)return l(s,!0);if(i)return i(s,!0);var c=new Error("Cannot find module '"+s+"'");throw c.code="MODULE_NOT_FOUND",c}var u=n[s]={exports:{}};t[s][0].call(u.exports,function(e){var n=t[s][1][e];return r(n||e)},u,u.exports,e,t,n,o)}return n[s].exports}for(var i="function"==typeof require&&require,s=0;s<o.length;s++)r(o[s]);return r}({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";function o(e){var t=d[e];if(void 0==t)throw new Error("could not find <details> element with id '"+e+"'");return t}function r(e){for(var t=e.target,n=t.id,r=o(n),i=r.element.open,s=0,l=r.toggles;s<l.length;s++){var c=l[s];c.classList.contains("details-toggle-control")&&(c.classList.add(i?"collapser":"expander"),c.classList.remove(i?"expander":"collapser"))}t.open==r.openByDefault?delete p[n]:p[n]=!0,a()}function i(){for(var e=0,t=Array.prototype.slice.call(document.getElementsByTagName("details"));e<t.length;e++){var n=t[e];"string"==typeof n.id&&n.id.length>0&&(d[n.id]={element:n,openByDefault:!!n.open,toggles:[]},n.addEventListener("toggle",r))}}function s(e){var t=o(e).element;t.open=!t.open}function a(){var e=Object.keys(p);document.cookie="toggled="+encodeURIComponent(e.join("+"))}function l(){var e=h.getCookie("toggled");if(e)for(var t=0,n=e.split("+");t<n.length;t++){var o=n[t],r=d[o];p[o]=!0,r&&(r.element.open=!r.element.open)}}function c(e){e.preventDefault();var t=e.currentTarget.getAttribute("data-details-id");if(!t)throw new Error("element with class 'details-toggle' has no 'data-details-id' attribute!");s(t)}function u(){Array.prototype.slice.call(document.getElementsByClassName("details-toggle")).forEach(function(e){var t=e.getAttribute("data-details-id");if(!t)throw new Error("element with class 'details-toggle' has no 'data-details-id' attribute!");var n=o(t);n.toggles.push(e),e.addEventListener("click",c),e.classList.contains("details-toggle-control")&&e.classList.add(n.element.open?"collapser":"expander")})}Object.defineProperty(n,"__esModule",{value:!0});var h=e("./cookies"),d={},p={};n.init=function(){i(),l(),u()}},{"./cookies":1}],3:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var o=e("./style-menu"),r=e("./details-helper"),i=e("./quick-jump");!function(e){"interactive"===document.readyState?e():document.addEventListener("readystatechange",function(){"interactive"===document.readyState&&e()})}(function(){document.body.classList.add("js-enabled"),o.init(),r.init(),i.init()})},{"./details-helper":2,"./quick-jump":4,"./style-menu":5}],4:[function(e,t,n){"use strict";function o(e,t,n){var o=new XMLHttpRequest;o.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()}function r(e){var t=document.querySelector("#page-menu"),n=document.createElement("li");t.insertBefore(n,t.firstChild),d.render(p(v,{onClick:e,title:"Quick Jump"}),t,n)}function i(e,t){return t.length<=e?t:t.slice(0,e)}function s(){return p("table",{class:"keyboard-shortcuts"},p("tr",null,p("th",null,"Key"),p("th",null,"Shortcut")),p("tr",null,p("td",null,p("span",{class:"key"},"s")),p("td",null,"Open this search box")),p("tr",null,p("td",null,p("span",{class:"key"},"esc")),p("td",null,"Close this search box")),p("tr",null,p("td",null,p("span",{class:"key"},"↓"),",",p("span",{class:"key"},"ctrl")," + ",p("span",{class:"key"},"j")),p("td",null,"Move down in search results")),p("tr",null,p("td",null,p("span",{class:"key"},"↑"),",",p("span",{class:"key"},"ctrl")," + ",p("span",{class:"key"},"k")),p("td",null,"Move up in search results")),p("tr",null,p("td",null,p("span",{class:"key"},"↵")),p("td",null,"Go to active search result")))}function a(){return p("p",null,"You can find any exported type, constructor, class, function or pattern defined in this package by (approximate) name.")}function l(e){var t=[p("p",null,"Your search for '",e.searchString,"' produced the following list of results: ",p("code",null,"[]"),"."),p("p",null,p("code",null,"Nothing")," matches your query for '",e.searchString,"'."),p("p",null,p("code",null,"Left \"no matches for '",e.searchString,"'\" :: Either String (NonEmpty SearchResult)"))];return t[(e.searchString||"a").charCodeAt(0)%t.length]}function c(e,t){d.render(p(g,{baseUrl:e||".",showHideTrigger:t||r}),document.body)}var u=this&&this.__extends||function(){var e=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])};return function(t,n){function o(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(o.prototype=n.prototype,new o)}}();Object.defineProperty(n,"__esModule",{value:!0});var h=e("fuse.js"),d=e("preact"),p=d.h,f=d.Component,v=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return u(t,e),t.prototype.render=function(e){return p("li",null,p("a",{href:"#",onClick:function(t){t.preventDefault(),e.onClick()}},e.title))},t}(f),g=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.linkIndex=0,t.focusPlease=!1,t.navigatedByKeyboard=!1,t}return u(t,e),t.prototype.componentWillMount=function(){var e=this;this.setState({searchString:"",isVisible:!1,expanded:{},activeLinkIndex:-1,moduleResults:[]}),o(this.props.baseUrl+"/doc-index.json",function(t){e.setState({fuse:new h(t,{threshold:.25,caseSensitive:!0,includeScore:!0,tokenize:!0,keys:[{name:"name",weight:.7},{name:"module",weight:.3}]}),moduleResults:[]})},function(t){console&&console.error("could not load 'doc-index.json' for searching",t),e.setState({failedLoading:!0})}),document.addEventListener("mousedown",this.hide.bind(this)),document.addEventListener("keydown",function(t){e.state.isVisible&&("Escape"===t.key?e.hide():"ArrowUp"===t.key||"k"===t.key&&t.ctrlKey?(t.preventDefault(),e.navigateLinks(-1)):"ArrowDown"===t.key||"j"===t.key&&t.ctrlKey?(t.preventDefault(),e.navigateLinks(1)):"Enter"===t.key&&e.state.activeLinkIndex>=0&&e.followActiveLink()),"s"===t.key&&"input"!==t.target.tagName.toLowerCase()&&(t.preventDefault(),e.show())})},t.prototype.hide=function(){this.setState({isVisible:!1,searchString:""})},t.prototype.show=function(){this.state.isVisible||(this.focusPlease=!0,this.setState({isVisible:!0,activeLinkIndex:-1}))},t.prototype.toggleVisibility=function(){this.state.isVisible?this.hide():this.show()},t.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})},t.prototype.followActiveLink=function(){this.activeLinkAction&&this.activeLinkAction()},t.prototype.updateResults=function(){var e=this.input&&this.input.value||"",t={};this.state.fuse.search(e).forEach(function(e){var n=e.item.module;(t[n]||(t[n]=[])).push(e)});var n=[];for(var o in t)!function(e){var o=t[e],r=0;o.forEach(function(e){r+=1/e.score}),n.push({module:e,totalScore:1/r,items:o})}(o);n.sort(function(e,t){return e.totalScore-t.totalScore}),this.setState({searchString:e,isVisible:!0,moduleResults:n})},t.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},t.prototype.componentDidMount=function(){this.props.showHideTrigger(this.toggleVisibility.bind(this))},t.prototype.render=function(e,t){var n=this;if(t.failedLoading){var o="file:"==window.location.protocol;return p("div",{id:"search",class:t.isVisible?"":"hidden"},p("div",{id:"search-results"},p("p",{class:"error"},"Failed to load file 'doc-index.json' containing definitions in this package."),o?p("p",{class:"error"},"To use quick jump, load this page with HTTP (from a local static file web server) instead of using the ",p("code",null,"file://")," protocol. (For security reasons, it is not possible to fetch auxiliary files using JS in a HTML page opened with ",p("code",null,"file://"),".)"):[]))}this.linkIndex=0;var r=function(e){e.stopPropagation()},c=i(10,t.moduleResults).map(function(e){return n.renderResultsInModule(e)});return p("div",{id:"search",class:t.isVisible?"":"hidden"},p("div",{id:"search-form",onMouseDown:r},p("input",{placeholder:"Search in package by name",ref:function(e){n.input=e},onFocus:this.show.bind(this),onClick:this.show.bind(this),onInput:this.updateResults.bind(this)})),p("div",{id:"search-results",ref:function(e){n.searchResults=e},onMouseDown:r,onMouseOver:function(e){for(var t=e.target;t&&"function"==typeof t.getAttribute;){var o=t.getAttribute("data-link-index");if("string"==typeof o){var r=parseInt(o,10);n.setState({activeLinkIndex:r});break}t=t.parentNode}}},""===t.searchString?[p(a,null),p(s,null)]:0==c.length?p(l,{searchString:t.searchString}):p("ul",null,c)))},t.prototype.renderResultsInModule=function(e){var t=this,n=e.items,o=e.module,r=this.state.expanded[o]||n.length<=10,s=r?n:i(8,n),a=function(e){return p("li",{class:"search-result"},t.navigationLink(t.props.baseUrl+"/"+e.link,{},p(m,{html:e.display_html})))};return p("li",{class:"search-module"},p("h4",null,o),p("ul",null,s.map(function(e){return a(e.item)}),r?[]:p("li",{class:"more-results"},this.actionLink(function(){var e=Object.assign({},t.state.expanded);e[o]=!0,t.setState({expanded:e})},{},"show "+(n.length-s.length)+" more results from this module"))))},t.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))},t.prototype.actionLink=function(e,t){for(var n=[],o=2;o<arguments.length;o++)n[o-2]=arguments[o];var r=Object.assign({href:"#",onClick:function(t){t.preventDefault(),e()}},t);return this.menuLink.apply(this,[r,e].concat(n))},t.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,p.apply(void 0,["a",s].concat(o))},t}(f),m=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return u(t,e),t.prototype.shouldComponentUpdate=function(e){return this.props.html!==e.html},t.prototype.render=function(e){return p("div",{dangerouslySetInnerHTML:{__html:e.html}})},t}(f);n.init=c,window.quickNav={init:c}},{"fuse.js":6,preact:7}],5:[function(e,t,n){"use strict";function o(e){return(" "+e+" ").replace(g," ")}function r(e){return e.replace(m,"")}function i(e,t){return o(e.className||"").indexOf(" "+t+" ")>=0}function s(e,t){var n=o(e.className||"");n.indexOf(" "+t+" ")<0&&(e.className=r(n+" "+t))}function a(e,t){var n=o(e.className||"");n=n.replace(" "+t+" "," "),e.className=r(n)}function l(e,t,n,o){return null==o&&(o=!i(e,t)),o?(a(e,n),s(e,t)):(a(e,t),s(e,n)),o}function c(e){var t=document.getElementById("page-menu");if(t&&t.firstChild){var n=t.firstChild.cloneNode(!1);n.innerHTML=e,t.appendChild(n)}}function u(){return Array.prototype.slice.call(document.getElementsByTagName("link")).filter(function(e){return-1!=e.rel.indexOf("style")&&e.title})}function h(){var e=u(),t="";e.forEach(function(e){t+="<li><a href='#' onclick=\"setActiveStyleSheet('"+e.title+"'); return false;\">"+e.title+"</a></li>"}),e.length>1&&c("<div id='style-menu-holder'><a href='#' onclick='styleMenu(); return false;'>Style ▾</a><ul id='style-menu' class='hide'>"+t+"</ul></div>")}function d(e){for(var t=u(),n=null,o=0;o<t.length;o++){var r=t[o];r.disabled=!0,r.title==e&&(n=r)}n?(n.disabled=!1,v.setCookie("haddock-style",e)):(t[0].disabled=!1,v.clearCookie("haddock-style")),f(!1)}function p(){var e=v.getCookie("haddock-style");e&&d(e)}function f(e){var t=document.getElementById("style-menu");t&&y(t,e)}Object.defineProperty(n,"__esModule",{value:!0});var v=e("./cookies"),g=/\s\s+/g,m=/^\s+|\s+$/g,y=function(e,t){return function(n,o){return l(n,e,t,o)}}("show","hide");n.init=function(){h(),p()}},{"./cookies":1}],6:[function(e,t,n){!function(e,o){"object"==typeof n&&"object"==typeof t?t.exports=o():"function"==typeof define&&define.amd?define("Fuse",[],o):"object"==typeof n?n.Fuse=o():e.Fuse=o()}(this,function(){return function(e){function t(o){if(n[o])return n[o].exports;var r=n[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,t),r.l=!0,r.exports}var n={};return t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,o){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:o})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=8)}([function(e,t,n){"use strict";e.exports=function(e){return"[object Array]"===Object.prototype.toString.call(e)}},function(e,t,n){"use strict";function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var r=function(){function e(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(t,n,o){return n&&e(t.prototype,n),o&&e(t,o),t}}(),i=n(5),s=n(7),a=n(4),l=function(){function e(t,n){var r=n.location,i=void 0===r?0:r,s=n.distance,l=void 0===s?100:s,c=n.threshold,u=void 0===c?.6:c,h=n.maxPatternLength,d=void 0===h?32:h,p=n.isCaseSensitive,f=void 0!==p&&p,v=n.tokenSeparator,g=void 0===v?/ +/g:v,m=n.findAllMatches,y=void 0!==m&&m,_=n.minMatchCharLength,k=void 0===_?1:_;o(this,e),this.options={location:i,distance:l,threshold:u,maxPatternLength:d,isCaseSensitive:f,tokenSeparator:g,findAllMatches:y,minMatchCharLength:k},this.pattern=this.options.isCaseSensitive?t:t.toLowerCase(),this.pattern.length<=d&&(this.patternAlphabet=a(this.pattern))}return r(e,[{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 i(e,this.pattern,o);var r=this.options,a=r.location,l=r.distance,c=r.threshold,u=r.findAllMatches,h=r.minMatchCharLength;return s(e,this.pattern,this.patternAlphabet,{location:a,distance:l,threshold:c,findAllMatches:u,minMatchCharLength:h})}}]),e}();e.exports=l},function(e,t,n){"use strict";var o=n(0),r=function e(t,n,r){if(n){var i=n.indexOf("."),s=n,a=null;-1!==i&&(s=n.slice(0,i),a=n.slice(i+1));var l=t[s];if(null!==l&&void 0!==l)if(a||"string"!=typeof l&&"number"!=typeof l)if(o(l))for(var c=0,u=l.length;c<u;c+=1)e(l[c],a,r);else a&&e(l,a,r);else r.push(l.toString())}else r.push(t);return r};e.exports=function(e,t){return r(e,t,[])}},function(e,t,n){"use strict";e.exports=function(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1&&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||((r=i-1)-o+1>=t&&n.push([o,r]),o=-1)}return e[i-1]&&i-o>=t&&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 o=/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g;e.exports=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:/ +/g,r=new RegExp(t.replace(o,"\\$&").replace(n,"|")),i=e.match(r),s=!!i,a=[];if(s)for(var l=0,c=i.length;l<c;l+=1){var u=i[l];a.push([e.indexOf(u),u.length-1])}return{score:s?.5:1,isMatch:s,matchedIndices:a}}},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 o=n(6),r=n(3);e.exports=function(e,t,n,i){for(var s=i.location,a=void 0===s?0:s,l=i.distance,c=void 0===l?100:l,u=i.threshold,h=void 0===u?.6:u,d=i.findAllMatches,p=void 0!==d&&d,f=i.minMatchCharLength,v=void 0===f?1:f,g=a,m=e.length,y=h,_=e.indexOf(t,g),k=t.length,b=[],x=0;x<m;x+=1)b[x]=0;if(-1!==_){var w=o(t,{errors:0,currentLocation:_,expectedLocation:g,distance:c});if(y=Math.min(w,y),-1!==(_=e.lastIndexOf(t,g+k))){var S=o(t,{errors:0,currentLocation:_,expectedLocation:g,distance:c});y=Math.min(S,y)}}_=-1;for(var L=[],C=1,M=k+m,N=1<<k-1,I=0;I<k;I+=1){for(var A=0,O=M;A<O;)o(t,{errors:I,currentLocation:g+O,expectedLocation:g,distance:c})<=y?A=O:M=O,O=Math.floor((M-A)/2+A);M=O;var E=Math.max(1,g-O+1),T=p?m:Math.min(g+O,m)+k,j=Array(T+2);j[T+1]=(1<<I)-1;for(var P=T;P>=E;P-=1){var R=P-1,U=n[e.charAt(R)];if(U&&(b[R]=1),j[P]=(j[P+1]<<1|1)&U,0!==I&&(j[P]|=(L[P+1]|L[P])<<1|1|L[P+1]),j[P]&N&&(C=o(t,{errors:I,currentLocation:R,expectedLocation:g,distance:c}))<=y){if(y=C,(_=R)<=g)break;E=Math.max(1,2*g-_)}}if(o(t,{errors:I+1,currentLocation:g,expectedLocation:g,distance:c})>y)break;L=j}return{isMatch:_>=0,score:0===C?.001:C,matchedIndices:r(b,v)}}},function(e,t,n){"use strict";function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var r=function(){function e(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(t,n,o){return n&&e(t.prototype,n),o&&e(t,o),t}}(),i=n(1),s=n(2),a=n(0),l=function(){function e(t,n){var r=n.location,i=void 0===r?0:r,a=n.distance,l=void 0===a?100:a,c=n.threshold,u=void 0===c?.6:c,h=n.maxPatternLength,d=void 0===h?32:h,p=n.caseSensitive,f=void 0!==p&&p,v=n.tokenSeparator,g=void 0===v?/ +/g:v,m=n.findAllMatches,y=void 0!==m&&m,_=n.minMatchCharLength,k=void 0===_?1:_,b=n.id,x=void 0===b?null:b,w=n.keys,S=void 0===w?[]:w,L=n.shouldSort,C=void 0===L||L,M=n.getFn,N=void 0===M?s:M,I=n.sortFn,A=void 0===I?function(e,t){return e.score-t.score}:I,O=n.tokenize,E=void 0!==O&&O,T=n.matchAllTokens,j=void 0!==T&&T,P=n.includeMatches,R=void 0!==P&&P,U=n.includeScore,D=void 0!==U&&U,V=n.verbose,F=void 0!==V&&V;o(this,e),this.options={location:i,distance:l,threshold:u,maxPatternLength:d,isCaseSensitive:f,tokenSeparator:g,findAllMatches:y,minMatchCharLength:k,id:x,keys:S,includeMatches:R,includeScore:D,shouldSort:C,getFn:N,sortFn:A,verbose:F,tokenize:E,matchAllTokens:j},this.setCollection(t)}return r(e,[{key:"setCollection",value:function(e){return this.list=e,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=arguments.length>0&&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=arguments.length>0&&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,d=this.options.keys.length;h<d;h+=1){var p=this.options.keys[h];if("string"!=typeof p){if(a[p.name]={weight:1-p.weight||1},p.weight<=0||p.weight>1)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,l=e.index,c=t.tokenSearchers,u=void 0===c?[]:c,h=t.fullSearcher,d=void 0===h?[]:h,p=t.resultMap,f=void 0===p?{}:p,v=t.results,g=void 0===v?[]:v;if(void 0!==i&&null!==i){var m=!1,y=-1,_=0;if("string"==typeof i){this._log("\nKey: "+(""===n?"-":n));var k=d.search(i);if(this._log('Full text: "'+i+'", score: '+k.score),this.options.tokenize){for(var b=i.split(this.options.tokenSeparator),x=[],w=0;w<u.length;w+=1){var S=u[w];this._log('\nPattern: "'+S.pattern+'"');for(var L=!1,C=0;C<b.length;C+=1){var M=b[C],N=S.search(M),I={};N.isMatch?(I[M]=N.score,m=!0,L=!0,x.push(N.score)):(I[M]=1,this.options.matchAllTokens||x.push(1)),this._log('Token: "'+M+'", score: '+I[M])}L&&(_+=1)}y=x[0];for(var A=x.length,O=1;O<A;O+=1)y+=x[O];y/=A,this._log("Token score average:",y)}var E=k.score;y>-1&&(E=(E+y)/2),this._log("Score average:",E);var T=!this.options.tokenize||!this.options.matchAllTokens||_>=u.length;if(this._log("\nCheck Matches: "+T),(m||k.isMatch)&&T){var j=f[l];j?j.output.push({key:n,arrayIndex:r,value:i,score:E,matchedIndices:k.matchedIndices}):(f[l]={item:s,output:[{key:n,arrayIndex:r,value:i,score:E,matchedIndices:k.matchedIndices}]},g.push(f[l]))}}else if(a(i))for(var P=0,R=i.length;P<R;P+=1)this._analyze({key:n,arrayIndex:P,value:i[P],record:s,index:l},{resultMap:f,results:g,tokenSearchers:u,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=0,a=1,l=0;l<i;l+=1){var c=r[l].score,u=e?e[r[l].key].weight:1,h=c*u;1!==u?a=Math.min(a,h):(r[l].nScore=h,s+=h)}t[n].score=1===a?s/i: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._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")&&i.arrayIndex>-1&&(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(){if(this.options.verbose){var e;(e=console).log.apply(e,arguments)}}}]),e}();e.exports=l}])})},{}],7:[function(e,t,n){!function(){"use strict";function e(){}function n(t,n){var o,r,i,s,a=O;for(s=arguments.length;s-- >2;)A.push(arguments[s]);for(n&&null!=n.children&&(A.length||A.push(n.children),delete n.children);A.length;)if((r=A.pop())&&void 0!==r.pop)for(s=r.length;s--;)A.push(r[s]);else"boolean"==typeof r&&(r=null),(i="function"!=typeof t)&&(null==r?r="":"number"==typeof r?r=String(r):"string"!=typeof r&&(i=!1)),i&&o?a[a.length-1]+=r:a===O?a=[r]:a.push(r),o=i;var l=new e;return l.nodeName=t,l.children=a,l.attributes=null==n?void 0:n,l.key=null==n?void 0:n.key,void 0!==I.vnode&&I.vnode(l),l}function o(e,t){for(var n in t)e[n]=t[n];return e}function r(e){!e.__d&&(e.__d=!0)&&1==j.push(e)&&(I.debounceRendering||E)(i)}function i(){var e,t=j;for(j=[];e=t.pop();)e.__d&&L(e)}function s(e,t,n){return"string"==typeof t||"number"==typeof t?void 0!==e.splitText:"string"==typeof t.nodeName?!e._componentConstructor&&a(e,t.nodeName):n||e._componentConstructor===t.nodeName}function a(e,t){return e.__n===t||e.nodeName.toLowerCase()===t.toLowerCase()}function l(e){var t=o({},e.attributes);t.children=e.children;var n=e.nodeName.defaultProps;if(void 0!==n)for(var r in n)void 0===t[r]&&(t[r]=n[r]);return t}function c(e,t){var n=t?document.createElementNS("http://www.w3.org/2000/svg",e):document.createElement(e);return n.__n=e,n}function u(e){var t=e.parentNode;t&&t.removeChild(e)}function h(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===T.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,p,s):e.removeEventListener(t,p,s),(e.__l||(e.__l={}))[t]=o}else if("list"!==t&&"type"!==t&&!r&&t in e)d(e,t,null==o?"":o),null!=o&&!1!==o||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 d(e,t,n){try{e[t]=n}catch(e){}}function p(e){return this.__l[e.type](I.event&&I.event(e)||e)}function f(){for(var e;e=P.pop();)I.afterMount&&I.afterMount(e),e.componentDidMount&&e.componentDidMount()}function v(e,t,n,o,r,i){R++||(U=null!=r&&void 0!==r.ownerSVGElement,D=null!=e&&!("__preactattr_"in e));var s=g(e,t,n,o,i);return r&&s.parentNode!==r&&r.appendChild(s),--R||(D=!1,i||f()),s}function g(e,t,n,o,r){var i=e,s=U;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),y(e,!0))),i.__preactattr_=!0,i;var l=t.nodeName;if("function"==typeof l)return C(e,t,n,o);if(U="svg"===l||"foreignObject"!==l&&U,l=String(l),(!e||!a(e,l))&&(i=c(l,U),e)){for(;e.firstChild;)i.appendChild(e.firstChild);e.parentNode&&e.parentNode.replaceChild(i,e),y(e,!0)}var u=i.firstChild,h=i.__preactattr_,d=t.children;if(null==h){h=i.__preactattr_={};for(var p=i.attributes,f=p.length;f--;)h[p[f].name]=p[f].value}return!D&&d&&1===d.length&&"string"==typeof d[0]&&null!=u&&void 0!==u.splitText&&null==u.nextSibling?u.nodeValue!=d[0]&&(u.nodeValue=d[0]):(d&&d.length||null!=u)&&m(i,d,n,o,D||null!=h.dangerouslySetInnerHTML),k(i,t.attributes,h),U=s,i}function m(e,t,n,o,r){var i,a,l,c,h,d=e.childNodes,p=[],f={},v=0,m=0,_=d.length,k=0,b=t?t.length:0;if(0!==_)for(L=0;L<_;L++){var x=d[L],w=x.__preactattr_;null!=(S=b&&w?x._component?x._component.__k:w.key:null)?(v++,f[S]=x):(w||(void 0!==x.splitText?!r||x.nodeValue.trim():r))&&(p[k++]=x)}if(0!==b)for(L=0;L<b;L++){h=null;var S=(c=t[L]).key;if(null!=S)v&&void 0!==f[S]&&(h=f[S],f[S]=void 0,v--);else if(!h&&m<k)for(i=m;i<k;i++)if(void 0!==p[i]&&s(a=p[i],c,r)){h=a,p[i]=void 0,i===k-1&&k--,i===m&&m++;break}h=g(h,c,n,o),l=d[L],h&&h!==e&&h!==l&&(null==l?e.appendChild(h):h===l.nextSibling?u(l):e.insertBefore(h,l))}if(v)for(var L in f)void 0!==f[L]&&y(f[L],!1);for(;m<=k;)void 0!==(h=p[k--])&&y(h,!1)}function y(e,t){var n=e._component;n?M(n):(null!=e.__preactattr_&&e.__preactattr_.ref&&e.__preactattr_.ref(null),!1!==t&&null!=e.__preactattr_||u(e),_(e))}function _(e){for(e=e.lastChild;e;){var t=e.previousSibling;y(e,!0),e=t}}function k(e,t,n){var o;for(o in n)t&&null!=t[o]||null==n[o]||h(e,o,n[o],n[o]=void 0,U);for(o in t)"children"===o||"innerHTML"===o||o in n&&t[o]===("value"===o||"checked"===o?e[o]:n[o])||h(e,o,n[o],n[o]=t[o],U)}function b(e){var t=e.constructor.name;(V[t]||(V[t]=[])).push(e)}function x(e,t,n){var o,r=V[e.name];if(e.prototype&&e.prototype.render?(o=new e(t,n),N.call(o,t,n)):((o=new N(t,n)).constructor=e,o.render=w),r)for(var i=r.length;i--;)if(r[i].constructor===e){o.__b=r[i].__b,r.splice(i,1);break}return o}function w(e,t,n){return this.constructor(e,n)}function S(e,t,n,o,i){e.__x||(e.__x=!0,(e.__r=t.ref)&&delete t.ref,(e.__k=t.key)&&delete t.key,!e.base||i?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===I.syncComponentUpdates&&e.base?r(e):L(e,1,i)),e.__r&&e.__r(e))}function L(e,t,n,r){if(!e.__x){var i,s,a,c=e.props,u=e.state,h=e.context,d=e.__p||c,p=e.__s||u,g=e.__c||h,m=e.base,_=e.__b,k=m||_,b=e._component,w=!1;if(m&&(e.props=d,e.state=p,e.context=g,2!==t&&e.shouldComponentUpdate&&!1===e.shouldComponentUpdate(c,u,h)?w=!0:e.componentWillUpdate&&e.componentWillUpdate(c,u,h),e.props=c,e.state=u,e.context=h),e.__p=e.__s=e.__c=e.__b=null,e.__d=!1,!w){i=e.render(c,u,h),e.getChildContext&&(h=o(o({},h),e.getChildContext()));var C,N,A=i&&i.nodeName;if("function"==typeof A){var O=l(i);(s=b)&&s.constructor===A&&O.key==s.__k?S(s,O,1,h,!1):(C=s,e._component=s=x(A,O,h),s.__b=s.__b||_,s.__u=e,S(s,O,0,h,!1),L(s,1,n,!0)),N=s.base}else a=k,(C=b)&&(a=e._component=null),(k||1===t)&&(a&&(a._component=null),N=v(a,i,h,n||!m,k&&k.parentNode,!0));if(k&&N!==k&&s!==b){var E=k.parentNode;E&&N!==E&&(E.replaceChild(N,k),C||(k._component=null,y(k,!1)))}if(C&&M(C),e.base=N,N&&!r){for(var T=e,j=e;j=j.__u;)(T=j).base=N;N._component=T,N._componentConstructor=T.constructor}}if(!m||n?P.unshift(e):w||(e.componentDidUpdate&&e.componentDidUpdate(d,p,g),I.afterUpdate&&I.afterUpdate(e)),null!=e.__h)for(;e.__h.length;)e.__h.pop().call(e);R||r||f()}}function C(e,t,n,o){for(var r=e&&e._component,i=r,s=e,a=r&&e._componentConstructor===t.nodeName,c=a,u=l(t);r&&!c&&(r=r.__u);)c=r.constructor===t.nodeName;return r&&c&&(!o||r._component)?(S(r,u,3,n,o),e=r.base):(i&&!a&&(M(i),e=s=null),r=x(t.nodeName,u,n),e&&!r.__b&&(r.__b=e,s=null),S(r,u,1,n,o),e=r.base,s&&e!==s&&(s._component=null,y(s,!1))),e}function M(e){I.beforeUnmount&&I.beforeUnmount(e);var t=e.base;e.__x=!0,e.componentWillUnmount&&e.componentWillUnmount(),e.base=null;var n=e._component;n?M(n):t&&(t.__preactattr_&&t.__preactattr_.ref&&t.__preactattr_.ref(null),e.__b=t,u(t),b(e),_(t)),e.__r&&e.__r(null)}function N(e,t){this.__d=!0,this.context=t,this.props=e,this.state=this.state||{}}var I={},A=[],O=[],E="function"==typeof Promise?Promise.resolve().then.bind(Promise.resolve()):setTimeout,T=/acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i,j=[],P=[],R=0,U=!1,D=!1,V={};o(N.prototype,{setState:function(e,t){var n=this.state;this.__s||(this.__s=o({},n)),o(n,"function"==typeof e?e(n,this.props):e),t&&(this.__h=this.__h||[]).push(t),r(this)},forceUpdate:function(e){e&&(this.__h=this.__h||[]).push(e),L(this,2)},render:function(){}});var F={h:n,createElement:n,cloneElement:function(e,t){return n(e.nodeName,o(o({},e.attributes),t),arguments.length>2?[].slice.call(arguments,2):e.children)},Component:N,render:function(e,t,n){return v(n,e,{},!1,t,!1)},rerender:i,options:I};void 0!==t?t.exports=F:self.preact=F}()},{}]},{},[3]);  //# sourceMappingURL=haddock-bundle.min.js.map diff --git a/haddock-api/resources/html/js-src/quick-jump.tsx b/haddock-api/resources/html/js-src/quick-jump.tsx index 97ac14af..e64dae0b 100644 --- a/haddock-api/resources/html/js-src/quick-jump.tsx +++ b/haddock-api/resources/html/js-src/quick-jump.tsx @@ -107,7 +107,15 @@ class QuickJump extends Component<QuickJumpProps, QuickJumpState> {            caseSensitive: true,            includeScore: true,            tokenize: true, -          keys: ["name", "module"] +          keys: [ { +                    name: "name", +                    weight: 0.7 +                  }, +                  { +                    name: "module", +                    weight: 0.3 +                  } +                ]          }),          moduleResults: []        }); @@ -143,7 +151,7 @@ class QuickJump extends Component<QuickJumpProps, QuickJumpState> {    }    hide() { -    this.setState({ isVisible: false }); +    this.setState({ isVisible: false, searchString: '' });    }    show() { @@ -409,4 +417,4 @@ export function init(docBaseUrl?: string, showHide?: (action: () => void) => voi  }  // export to global object -(window as any).quickNav = { init: init };
\ No newline at end of file +(window as any).quickNav = { init: init }; diff --git a/haddock-api/resources/html/quick-jump.css b/haddock-api/resources/html/quick-jump.css index ede05042..468d8036 100644 --- a/haddock-api/resources/html/quick-jump.css +++ b/haddock-api/resources/html/quick-jump.css @@ -8,6 +8,7 @@    width: 44em;    z-index: 1000;    pointer-events: none; +  overflow-y: auto;  }  #search.hidden { @@ -42,7 +43,6 @@    box-sizing: border-box;    border: 0.05em solid #b2d5fb;    background: #e8f3ff; -  overflow-y: auto;  }  #search-form input + #search-results { @@ -161,4 +161,4 @@    margin: 0 0.1em;  } -/* @end */
\ No newline at end of file +/* @end */ diff --git a/haddock-api/resources/html/quick-jump.min.js b/haddock-api/resources/html/quick-jump.min.js index f22f8f28..c03e0836 100644 --- a/haddock-api/resources/html/quick-jump.min.js +++ b/haddock-api/resources/html/quick-jump.min.js @@ -1,2 +1,2 @@ -!function e(t,n,o){function r(s,a){if(!n[s]){if(!t[s]){var l="function"==typeof require&&require;if(!a&&l)return l(s,!0);if(i)return i(s,!0);var c=new Error("Cannot find module '"+s+"'");throw c.code="MODULE_NOT_FOUND",c}var u=n[s]={exports:{}};t[s][0].call(u.exports,function(e){var n=t[s][1][e];return r(n||e)},u,u.exports,e,t,n,o)}return n[s].exports}for(var i="function"==typeof require&&require,s=0;s<o.length;s++)r(o[s]);return r}({1:[function(e,t,n){"use strict";function o(e,t,n){var o=new XMLHttpRequest;o.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()}function r(e){var t=document.querySelector("#page-menu"),n=document.createElement("li");t.insertBefore(n,t.firstChild),p.render(d(v,{onClick:e,title:"Quick Jump"}),t,n)}function i(e,t){return t.length<=e?t:t.slice(0,e)}function s(){return d("table",{class:"keyboard-shortcuts"},d("tr",null,d("th",null,"Key"),d("th",null,"Shortcut")),d("tr",null,d("td",null,d("span",{class:"key"},"s")),d("td",null,"Open this search box")),d("tr",null,d("td",null,d("span",{class:"key"},"esc")),d("td",null,"Close this search box")),d("tr",null,d("td",null,d("span",{class:"key"},"↓"),",",d("span",{class:"key"},"ctrl")," + ",d("span",{class:"key"},"j")),d("td",null,"Move down in search results")),d("tr",null,d("td",null,d("span",{class:"key"},"↑"),",",d("span",{class:"key"},"ctrl")," + ",d("span",{class:"key"},"k")),d("td",null,"Move up in search results")),d("tr",null,d("td",null,d("span",{class:"key"},"↵")),d("td",null,"Go to active search result")))}function a(){return d("p",null,"You can find any exported type, constructor, class, function or pattern defined in this package by (approximate) name.")}function l(e){var t=[d("p",null,"Your search for '",e.searchString,"' produced the following list of results: ",d("code",null,"[]"),"."),d("p",null,d("code",null,"Nothing")," matches your query for '",e.searchString,"'."),d("p",null,d("code",null,"Left \"no matches for '",e.searchString,"'\" :: Either String (NonEmpty SearchResult)"))];return t[(e.searchString||"a").charCodeAt(0)%t.length]}function c(e,t){p.render(d(_,{baseUrl:e||".",showHideTrigger:t||r}),document.body)}var u=this&&this.__extends||function(){var e=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])};return function(t,n){function o(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(o.prototype=n.prototype,new o)}}();Object.defineProperty(n,"__esModule",{value:!0});var h=e("fuse.js"),p=e("preact"),d=p.h,f=p.Component,v=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return u(t,e),t.prototype.render=function(e){return d("li",null,d("a",{href:"#",onClick:function(t){t.preventDefault(),e.onClick()}},e.title))},t}(f),_=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.linkIndex=0,t.focusPlease=!1,t.navigatedByKeyboard=!1,t}return u(t,e),t.prototype.componentWillMount=function(){var e=this;this.setState({searchString:"",isVisible:!1,expanded:{},activeLinkIndex:-1,moduleResults:[]}),o(this.props.baseUrl+"/doc-index.json",function(t){e.setState({fuse:new h(t,{threshold:.25,caseSensitive:!0,includeScore:!0,tokenize:!0,keys:["name","module"]}),moduleResults:[]})},function(t){console&&console.error("could not load 'doc-index.json' for searching",t),e.setState({failedLoading:!0})}),document.addEventListener("mousedown",this.hide.bind(this)),document.addEventListener("keydown",function(t){e.state.isVisible&&("Escape"===t.key?e.hide():"ArrowUp"===t.key||"k"===t.key&&t.ctrlKey?(t.preventDefault(),e.navigateLinks(-1)):"ArrowDown"===t.key||"j"===t.key&&t.ctrlKey?(t.preventDefault(),e.navigateLinks(1)):"Enter"===t.key&&e.state.activeLinkIndex>=0&&e.followActiveLink()),"s"===t.key&&"input"!==t.target.tagName.toLowerCase()&&(t.preventDefault(),e.show())})},t.prototype.hide=function(){this.setState({isVisible:!1})},t.prototype.show=function(){this.state.isVisible||(this.focusPlease=!0,this.setState({isVisible:!0,activeLinkIndex:-1}))},t.prototype.toggleVisibility=function(){this.state.isVisible?this.hide():this.show()},t.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})},t.prototype.followActiveLink=function(){this.activeLinkAction&&this.activeLinkAction()},t.prototype.updateResults=function(){var e=this.input&&this.input.value||"",t={};this.state.fuse.search(e).forEach(function(e){var n=e.item.module;(t[n]||(t[n]=[])).push(e)});var n=[];for(var o in t)!function(e){var o=t[e],r=0;o.forEach(function(e){r+=1/e.score}),n.push({module:e,totalScore:1/r,items:o})}(o);n.sort(function(e,t){return e.totalScore-t.totalScore}),this.setState({searchString:e,isVisible:!0,moduleResults:n})},t.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},t.prototype.componentDidMount=function(){this.props.showHideTrigger(this.toggleVisibility.bind(this))},t.prototype.render=function(e,t){var n=this;if(t.failedLoading){var o="file:"==window.location.protocol;return d("div",{id:"search",class:t.isVisible?"":"hidden"},d("div",{id:"search-results"},d("p",{class:"error"},"Failed to load file 'doc-index.json' containing definitions in this package."),o?d("p",{class:"error"},"To use quick jump, load this page with HTTP (from a local static file web server) instead of using the ",d("code",null,"file://")," protocol. (For security reasons, it is not possible to fetch auxiliary files using JS in a HTML page opened with ",d("code",null,"file://"),".)"):[]))}this.linkIndex=0;var r=function(e){e.stopPropagation()},c=i(10,t.moduleResults).map(function(e){return n.renderResultsInModule(e)});return d("div",{id:"search",class:t.isVisible?"":"hidden"},d("div",{id:"search-form",onMouseDown:r},d("input",{placeholder:"Search in package by name",ref:function(e){n.input=e},onFocus:this.show.bind(this),onClick:this.show.bind(this),onInput:this.updateResults.bind(this)})),d("div",{id:"search-results",ref:function(e){n.searchResults=e},onMouseDown:r,onMouseOver:function(e){for(var t=e.target;t&&"function"==typeof t.getAttribute;){var o=t.getAttribute("data-link-index");if("string"==typeof o){var r=parseInt(o,10);n.setState({activeLinkIndex:r});break}t=t.parentNode}}},""===t.searchString?[d(a,null),d(s,null)]:0==c.length?d(l,{searchString:t.searchString}):d("ul",null,c)))},t.prototype.renderResultsInModule=function(e){var t=this,n=e.items,o=e.module,r=this.state.expanded[o]||n.length<=10,s=r?n:i(8,n),a=function(e){return d("li",{class:"search-result"},t.navigationLink(t.props.baseUrl+"/"+e.link,{},d(g,{html:e.display_html})))};return d("li",{class:"search-module"},d("h4",null,o),d("ul",null,s.map(function(e){return a(e.item)}),r?[]:d("li",{class:"more-results"},this.actionLink(function(){var e=Object.assign({},t.state.expanded);e[o]=!0,t.setState({expanded:e})},{},"show "+(n.length-s.length)+" more results from this module"))))},t.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),s=function(){window.location.href=e,n.hide()};return this.menuLink.apply(this,[i,s].concat(o))},t.prototype.actionLink=function(e,t){for(var n=[],o=2;o<arguments.length;o++)n[o-2]=arguments[o];var r=Object.assign({href:"#",onClick:function(t){t.preventDefault(),e()}},t);return this.menuLink.apply(this,[r,e].concat(n))},t.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,d.apply(void 0,["a",s].concat(o))},t}(f),g=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return u(t,e),t.prototype.shouldComponentUpdate=function(e){return this.props.html!==e.html},t.prototype.render=function(e){return d("div",{dangerouslySetInnerHTML:{__html:e.html}})},t}(f);n.init=c,window.quickNav={init:c}},{"fuse.js":2,preact:3}],2:[function(e,t,n){!function(e,o){"object"==typeof n&&"object"==typeof t?t.exports=o():"function"==typeof define&&define.amd?define("Fuse",[],o):"object"==typeof n?n.Fuse=o():e.Fuse=o()}(this,function(){return function(e){function t(o){if(n[o])return n[o].exports;var r=n[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,t),r.l=!0,r.exports}var n={};return t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,o){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:o})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=8)}([function(e,t,n){"use strict";e.exports=function(e){return"[object Array]"===Object.prototype.toString.call(e)}},function(e,t,n){"use strict";function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var r=function(){function e(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(t,n,o){return n&&e(t.prototype,n),o&&e(t,o),t}}(),i=n(5),s=n(7),a=n(4),l=function(){function e(t,n){var r=n.location,i=void 0===r?0:r,s=n.distance,l=void 0===s?100:s,c=n.threshold,u=void 0===c?.6:c,h=n.maxPatternLength,p=void 0===h?32:h,d=n.isCaseSensitive,f=void 0!==d&&d,v=n.tokenSeparator,_=void 0===v?/ +/g:v,g=n.findAllMatches,m=void 0!==g&&g,y=n.minMatchCharLength,k=void 0===y?1:y;o(this,e),this.options={location:i,distance:l,threshold:u,maxPatternLength:p,isCaseSensitive:f,tokenSeparator:_,findAllMatches:m,minMatchCharLength:k},this.pattern=this.options.isCaseSensitive?t:t.toLowerCase(),this.pattern.length<=p&&(this.patternAlphabet=a(this.pattern))}return r(e,[{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 i(e,this.pattern,o);var r=this.options,a=r.location,l=r.distance,c=r.threshold,u=r.findAllMatches,h=r.minMatchCharLength;return s(e,this.pattern,this.patternAlphabet,{location:a,distance:l,threshold:c,findAllMatches:u,minMatchCharLength:h})}}]),e}();e.exports=l},function(e,t,n){"use strict";var o=n(0),r=function e(t,n,r){if(n){var i=n.indexOf("."),s=n,a=null;-1!==i&&(s=n.slice(0,i),a=n.slice(i+1));var l=t[s];if(null!==l&&void 0!==l)if(a||"string"!=typeof l&&"number"!=typeof l)if(o(l))for(var c=0,u=l.length;c<u;c+=1)e(l[c],a,r);else a&&e(l,a,r);else r.push(l.toString())}else r.push(t);return r};e.exports=function(e,t){return r(e,t,[])}},function(e,t,n){"use strict";e.exports=function(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1&&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||((r=i-1)-o+1>=t&&n.push([o,r]),o=-1)}return e[i-1]&&i-o>=t&&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 o=/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g;e.exports=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:/ +/g,r=new RegExp(t.replace(o,"\\$&").replace(n,"|")),i=e.match(r),s=!!i,a=[];if(s)for(var l=0,c=i.length;l<c;l+=1){var u=i[l];a.push([e.indexOf(u),u.length-1])}return{score:s?.5:1,isMatch:s,matchedIndices:a}}},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 o=n(6),r=n(3);e.exports=function(e,t,n,i){for(var s=i.location,a=void 0===s?0:s,l=i.distance,c=void 0===l?100:l,u=i.threshold,h=void 0===u?.6:u,p=i.findAllMatches,d=void 0!==p&&p,f=i.minMatchCharLength,v=void 0===f?1:f,_=a,g=e.length,m=h,y=e.indexOf(t,_),k=t.length,b=[],x=0;x<g;x+=1)b[x]=0;if(-1!==y){var w=o(t,{errors:0,currentLocation:y,expectedLocation:_,distance:c});if(m=Math.min(w,m),-1!==(y=e.lastIndexOf(t,_+k))){var S=o(t,{errors:0,currentLocation:y,expectedLocation:_,distance:c});m=Math.min(S,m)}}y=-1;for(var L=[],C=1,M=k+g,N=1<<k-1,I=0;I<k;I+=1){for(var A=0,T=M;A<T;)o(t,{errors:I,currentLocation:_+T,expectedLocation:_,distance:c})<=m?A=T:M=T,T=Math.floor((M-A)/2+A);M=T;var O=Math.max(1,_-T+1),j=d?g:Math.min(_+T,g)+k,P=Array(j+2);P[j+1]=(1<<I)-1;for(var E=j;E>=O;E-=1){var R=E-1,U=n[e.charAt(R)];if(U&&(b[R]=1),P[E]=(P[E+1]<<1|1)&U,0!==I&&(P[E]|=(L[E+1]|L[E])<<1|1|L[E+1]),P[E]&N&&(C=o(t,{errors:I,currentLocation:R,expectedLocation:_,distance:c}))<=m){if(m=C,(y=R)<=_)break;O=Math.max(1,2*_-y)}}if(o(t,{errors:I+1,currentLocation:_,expectedLocation:_,distance:c})>m)break;L=P}return{isMatch:y>=0,score:0===C?.001:C,matchedIndices:r(b,v)}}},function(e,t,n){"use strict";function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var r=function(){function e(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(t,n,o){return n&&e(t.prototype,n),o&&e(t,o),t}}(),i=n(1),s=n(2),a=n(0),l=function(){function e(t,n){var r=n.location,i=void 0===r?0:r,a=n.distance,l=void 0===a?100:a,c=n.threshold,u=void 0===c?.6:c,h=n.maxPatternLength,p=void 0===h?32:h,d=n.caseSensitive,f=void 0!==d&&d,v=n.tokenSeparator,_=void 0===v?/ +/g:v,g=n.findAllMatches,m=void 0!==g&&g,y=n.minMatchCharLength,k=void 0===y?1:y,b=n.id,x=void 0===b?null:b,w=n.keys,S=void 0===w?[]:w,L=n.shouldSort,C=void 0===L||L,M=n.getFn,N=void 0===M?s:M,I=n.sortFn,A=void 0===I?function(e,t){return e.score-t.score}:I,T=n.tokenize,O=void 0!==T&&T,j=n.matchAllTokens,P=void 0!==j&&j,E=n.includeMatches,R=void 0!==E&&E,U=n.includeScore,D=void 0!==U&&U,V=n.verbose,F=void 0!==V&&V;o(this,e),this.options={location:i,distance:l,threshold:u,maxPatternLength:p,isCaseSensitive:f,tokenSeparator:_,findAllMatches:m,minMatchCharLength:k,id:x,keys:S,includeMatches:R,includeScore:D,shouldSort:C,getFn:N,sortFn:A,verbose:F,tokenize:O,matchAllTokens:P},this.setCollection(t)}return r(e,[{key:"setCollection",value:function(e){return this.list=e,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=arguments.length>0&&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=arguments.length>0&&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||d.weight>1)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,l=e.index,c=t.tokenSearchers,u=void 0===c?[]:c,h=t.fullSearcher,p=void 0===h?[]:h,d=t.resultMap,f=void 0===d?{}:d,v=t.results,_=void 0===v?[]:v;if(void 0!==i&&null!==i){var g=!1,m=-1,y=0;if("string"==typeof i){this._log("\nKey: "+(""===n?"-":n));var k=p.search(i);if(this._log('Full text: "'+i+'", score: '+k.score),this.options.tokenize){for(var b=i.split(this.options.tokenSeparator),x=[],w=0;w<u.length;w+=1){var S=u[w];this._log('\nPattern: "'+S.pattern+'"');for(var L=!1,C=0;C<b.length;C+=1){var M=b[C],N=S.search(M),I={};N.isMatch?(I[M]=N.score,g=!0,L=!0,x.push(N.score)):(I[M]=1,this.options.matchAllTokens||x.push(1)),this._log('Token: "'+M+'", score: '+I[M])}L&&(y+=1)}m=x[0];for(var A=x.length,T=1;T<A;T+=1)m+=x[T];m/=A,this._log("Token score average:",m)}var O=k.score;m>-1&&(O=(O+m)/2),this._log("Score average:",O);var j=!this.options.tokenize||!this.options.matchAllTokens||y>=u.length;if(this._log("\nCheck Matches: "+j),(g||k.isMatch)&&j){var P=f[l];P?P.output.push({key:n,arrayIndex:r,value:i,score:O,matchedIndices:k.matchedIndices}):(f[l]={item:s,output:[{key:n,arrayIndex:r,value:i,score:O,matchedIndices:k.matchedIndices}]},_.push(f[l]))}}else if(a(i))for(var E=0,R=i.length;E<R;E+=1)this._analyze({key:n,arrayIndex:E,value:i[E],record:s,index:l},{resultMap:f,results:_,tokenSearchers:u,fullSearcher:p})}}},{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=0,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):(r[l].nScore=u,s+=u)}t[n].score=1===a?s/i: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._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")&&i.arrayIndex>-1&&(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(){if(this.options.verbose){var e;(e=console).log.apply(e,arguments)}}}]),e}();e.exports=l}])})},{}],3:[function(e,t,n){!function(){"use strict";function e(){}function n(t,n){var o,r,i,s,a=T;for(s=arguments.length;s-- >2;)A.push(arguments[s]);for(n&&null!=n.children&&(A.length||A.push(n.children),delete n.children);A.length;)if((r=A.pop())&&void 0!==r.pop)for(s=r.length;s--;)A.push(r[s]);else"boolean"==typeof r&&(r=null),(i="function"!=typeof t)&&(null==r?r="":"number"==typeof r?r=String(r):"string"!=typeof r&&(i=!1)),i&&o?a[a.length-1]+=r:a===T?a=[r]:a.push(r),o=i;var l=new e;return l.nodeName=t,l.children=a,l.attributes=null==n?void 0:n,l.key=null==n?void 0:n.key,void 0!==I.vnode&&I.vnode(l),l}function o(e,t){for(var n in t)e[n]=t[n];return e}function r(e){!e.__d&&(e.__d=!0)&&1==P.push(e)&&(I.debounceRendering||O)(i)}function i(){var e,t=P;for(P=[];e=t.pop();)e.__d&&L(e)}function s(e,t,n){return"string"==typeof t||"number"==typeof t?void 0!==e.splitText:"string"==typeof t.nodeName?!e._componentConstructor&&a(e,t.nodeName):n||e._componentConstructor===t.nodeName}function a(e,t){return e.__n===t||e.nodeName.toLowerCase()===t.toLowerCase()}function l(e){var t=o({},e.attributes);t.children=e.children;var n=e.nodeName.defaultProps;if(void 0!==n)for(var r in n)void 0===t[r]&&(t[r]=n[r]);return t}function c(e,t){var n=t?document.createElementNS("http://www.w3.org/2000/svg",e):document.createElement(e);return n.__n=e,n}function u(e){var t=e.parentNode;t&&t.removeChild(e)}function h(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===j.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,d,s):e.removeEventListener(t,d,s),(e.__l||(e.__l={}))[t]=o}else if("list"!==t&&"type"!==t&&!r&&t in e)p(e,t,null==o?"":o),null!=o&&!1!==o||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 p(e,t,n){try{e[t]=n}catch(e){}}function d(e){return this.__l[e.type](I.event&&I.event(e)||e)}function f(){for(var e;e=E.pop();)I.afterMount&&I.afterMount(e),e.componentDidMount&&e.componentDidMount()}function v(e,t,n,o,r,i){R++||(U=null!=r&&void 0!==r.ownerSVGElement,D=null!=e&&!("__preactattr_"in e));var s=_(e,t,n,o,i);return r&&s.parentNode!==r&&r.appendChild(s),--R||(D=!1,i||f()),s}function _(e,t,n,o,r){var i=e,s=U;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),m(e,!0))),i.__preactattr_=!0,i;var l=t.nodeName;if("function"==typeof l)return C(e,t,n,o);if(U="svg"===l||"foreignObject"!==l&&U,l=String(l),(!e||!a(e,l))&&(i=c(l,U),e)){for(;e.firstChild;)i.appendChild(e.firstChild);e.parentNode&&e.parentNode.replaceChild(i,e),m(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!D&&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)&&g(i,p,n,o,D||null!=h.dangerouslySetInnerHTML),k(i,t.attributes,h),U=s,i}function g(e,t,n,o,r){var i,a,l,c,h,p=e.childNodes,d=[],f={},v=0,g=0,y=p.length,k=0,b=t?t.length:0;if(0!==y)for(L=0;L<y;L++){var x=p[L],w=x.__preactattr_;null!=(S=b&&w?x._component?x._component.__k:w.key:null)?(v++,f[S]=x):(w||(void 0!==x.splitText?!r||x.nodeValue.trim():r))&&(d[k++]=x)}if(0!==b)for(L=0;L<b;L++){h=null;var S=(c=t[L]).key;if(null!=S)v&&void 0!==f[S]&&(h=f[S],f[S]=void 0,v--);else if(!h&&g<k)for(i=g;i<k;i++)if(void 0!==d[i]&&s(a=d[i],c,r)){h=a,d[i]=void 0,i===k-1&&k--,i===g&&g++;break}h=_(h,c,n,o),l=p[L],h&&h!==e&&h!==l&&(null==l?e.appendChild(h):h===l.nextSibling?u(l):e.insertBefore(h,l))}if(v)for(var L in f)void 0!==f[L]&&m(f[L],!1);for(;g<=k;)void 0!==(h=d[k--])&&m(h,!1)}function m(e,t){var n=e._component;n?M(n):(null!=e.__preactattr_&&e.__preactattr_.ref&&e.__preactattr_.ref(null),!1!==t&&null!=e.__preactattr_||u(e),y(e))}function y(e){for(e=e.lastChild;e;){var t=e.previousSibling;m(e,!0),e=t}}function k(e,t,n){var o;for(o in n)t&&null!=t[o]||null==n[o]||h(e,o,n[o],n[o]=void 0,U);for(o in t)"children"===o||"innerHTML"===o||o in n&&t[o]===("value"===o||"checked"===o?e[o]:n[o])||h(e,o,n[o],n[o]=t[o],U)}function b(e){var t=e.constructor.name;(V[t]||(V[t]=[])).push(e)}function x(e,t,n){var o,r=V[e.name];if(e.prototype&&e.prototype.render?(o=new e(t,n),N.call(o,t,n)):((o=new N(t,n)).constructor=e,o.render=w),r)for(var i=r.length;i--;)if(r[i].constructor===e){o.__b=r[i].__b,r.splice(i,1);break}return o}function w(e,t,n){return this.constructor(e,n)}function S(e,t,n,o,i){e.__x||(e.__x=!0,(e.__r=t.ref)&&delete t.ref,(e.__k=t.key)&&delete t.key,!e.base||i?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===I.syncComponentUpdates&&e.base?r(e):L(e,1,i)),e.__r&&e.__r(e))}function L(e,t,n,r){if(!e.__x){var i,s,a,c=e.props,u=e.state,h=e.context,p=e.__p||c,d=e.__s||u,_=e.__c||h,g=e.base,y=e.__b,k=g||y,b=e._component,w=!1;if(g&&(e.props=p,e.state=d,e.context=_,2!==t&&e.shouldComponentUpdate&&!1===e.shouldComponentUpdate(c,u,h)?w=!0:e.componentWillUpdate&&e.componentWillUpdate(c,u,h),e.props=c,e.state=u,e.context=h),e.__p=e.__s=e.__c=e.__b=null,e.__d=!1,!w){i=e.render(c,u,h),e.getChildContext&&(h=o(o({},h),e.getChildContext()));var C,N,A=i&&i.nodeName;if("function"==typeof A){var T=l(i);(s=b)&&s.constructor===A&&T.key==s.__k?S(s,T,1,h,!1):(C=s,e._component=s=x(A,T,h),s.__b=s.__b||y,s.__u=e,S(s,T,0,h,!1),L(s,1,n,!0)),N=s.base}else a=k,(C=b)&&(a=e._component=null),(k||1===t)&&(a&&(a._component=null),N=v(a,i,h,n||!g,k&&k.parentNode,!0));if(k&&N!==k&&s!==b){var O=k.parentNode;O&&N!==O&&(O.replaceChild(N,k),C||(k._component=null,m(k,!1)))}if(C&&M(C),e.base=N,N&&!r){for(var j=e,P=e;P=P.__u;)(j=P).base=N;N._component=j,N._componentConstructor=j.constructor}}if(!g||n?E.unshift(e):w||(e.componentDidUpdate&&e.componentDidUpdate(p,d,_),I.afterUpdate&&I.afterUpdate(e)),null!=e.__h)for(;e.__h.length;)e.__h.pop().call(e);R||r||f()}}function C(e,t,n,o){for(var r=e&&e._component,i=r,s=e,a=r&&e._componentConstructor===t.nodeName,c=a,u=l(t);r&&!c&&(r=r.__u);)c=r.constructor===t.nodeName;return r&&c&&(!o||r._component)?(S(r,u,3,n,o),e=r.base):(i&&!a&&(M(i),e=s=null),r=x(t.nodeName,u,n),e&&!r.__b&&(r.__b=e,s=null),S(r,u,1,n,o),e=r.base,s&&e!==s&&(s._component=null,m(s,!1))),e}function M(e){I.beforeUnmount&&I.beforeUnmount(e);var t=e.base;e.__x=!0,e.componentWillUnmount&&e.componentWillUnmount(),e.base=null;var n=e._component;n?M(n):t&&(t.__preactattr_&&t.__preactattr_.ref&&t.__preactattr_.ref(null),e.__b=t,u(t),b(e),y(t)),e.__r&&e.__r(null)}function N(e,t){this.__d=!0,this.context=t,this.props=e,this.state=this.state||{}}var I={},A=[],T=[],O="function"==typeof Promise?Promise.resolve().then.bind(Promise.resolve()):setTimeout,j=/acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i,P=[],E=[],R=0,U=!1,D=!1,V={};o(N.prototype,{setState:function(e,t){var n=this.state;this.__s||(this.__s=o({},n)),o(n,"function"==typeof e?e(n,this.props):e),t&&(this.__h=this.__h||[]).push(t),r(this)},forceUpdate:function(e){e&&(this.__h=this.__h||[]).push(e),L(this,2)},render:function(){}});var F={h:n,createElement:n,cloneElement:function(e,t){return n(e.nodeName,o(o({},e.attributes),t),arguments.length>2?[].slice.call(arguments,2):e.children)},Component:N,render:function(e,t,n){return v(n,e,{},!1,t,!1)},rerender:i,options:I};void 0!==t?t.exports=F:self.preact=F}()},{}]},{},[1]); +!function e(t,n,o){function r(s,a){if(!n[s]){if(!t[s]){var l="function"==typeof require&&require;if(!a&&l)return l(s,!0);if(i)return i(s,!0);var c=new Error("Cannot find module '"+s+"'");throw c.code="MODULE_NOT_FOUND",c}var u=n[s]={exports:{}};t[s][0].call(u.exports,function(e){var n=t[s][1][e];return r(n||e)},u,u.exports,e,t,n,o)}return n[s].exports}for(var i="function"==typeof require&&require,s=0;s<o.length;s++)r(o[s]);return r}({1:[function(e,t,n){"use strict";function o(e,t,n){var o=new XMLHttpRequest;o.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()}function r(e){var t=document.querySelector("#page-menu"),n=document.createElement("li");t.insertBefore(n,t.firstChild),p.render(d(v,{onClick:e,title:"Quick Jump"}),t,n)}function i(e,t){return t.length<=e?t:t.slice(0,e)}function s(){return d("table",{class:"keyboard-shortcuts"},d("tr",null,d("th",null,"Key"),d("th",null,"Shortcut")),d("tr",null,d("td",null,d("span",{class:"key"},"s")),d("td",null,"Open this search box")),d("tr",null,d("td",null,d("span",{class:"key"},"esc")),d("td",null,"Close this search box")),d("tr",null,d("td",null,d("span",{class:"key"},"↓"),",",d("span",{class:"key"},"ctrl")," + ",d("span",{class:"key"},"j")),d("td",null,"Move down in search results")),d("tr",null,d("td",null,d("span",{class:"key"},"↑"),",",d("span",{class:"key"},"ctrl")," + ",d("span",{class:"key"},"k")),d("td",null,"Move up in search results")),d("tr",null,d("td",null,d("span",{class:"key"},"↵")),d("td",null,"Go to active search result")))}function a(){return d("p",null,"You can find any exported type, constructor, class, function or pattern defined in this package by (approximate) name.")}function l(e){var t=[d("p",null,"Your search for '",e.searchString,"' produced the following list of results: ",d("code",null,"[]"),"."),d("p",null,d("code",null,"Nothing")," matches your query for '",e.searchString,"'."),d("p",null,d("code",null,"Left \"no matches for '",e.searchString,"'\" :: Either String (NonEmpty SearchResult)"))];return t[(e.searchString||"a").charCodeAt(0)%t.length]}function c(e,t){p.render(d(_,{baseUrl:e||".",showHideTrigger:t||r}),document.body)}var u=this&&this.__extends||function(){var e=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])};return function(t,n){function o(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(o.prototype=n.prototype,new o)}}();Object.defineProperty(n,"__esModule",{value:!0});var h=e("fuse.js"),p=e("preact"),d=p.h,f=p.Component,v=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return u(t,e),t.prototype.render=function(e){return d("li",null,d("a",{href:"#",onClick:function(t){t.preventDefault(),e.onClick()}},e.title))},t}(f),_=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.linkIndex=0,t.focusPlease=!1,t.navigatedByKeyboard=!1,t}return u(t,e),t.prototype.componentWillMount=function(){var e=this;this.setState({searchString:"",isVisible:!1,expanded:{},activeLinkIndex:-1,moduleResults:[]}),o(this.props.baseUrl+"/doc-index.json",function(t){e.setState({fuse:new h(t,{threshold:.25,caseSensitive:!0,includeScore:!0,tokenize:!0,keys:[{name:"name",weight:.7},{name:"module",weight:.3}]}),moduleResults:[]})},function(t){console&&console.error("could not load 'doc-index.json' for searching",t),e.setState({failedLoading:!0})}),document.addEventListener("mousedown",this.hide.bind(this)),document.addEventListener("keydown",function(t){e.state.isVisible&&("Escape"===t.key?e.hide():"ArrowUp"===t.key||"k"===t.key&&t.ctrlKey?(t.preventDefault(),e.navigateLinks(-1)):"ArrowDown"===t.key||"j"===t.key&&t.ctrlKey?(t.preventDefault(),e.navigateLinks(1)):"Enter"===t.key&&e.state.activeLinkIndex>=0&&e.followActiveLink()),"s"===t.key&&"input"!==t.target.tagName.toLowerCase()&&(t.preventDefault(),e.show())})},t.prototype.hide=function(){this.setState({isVisible:!1,searchString:""})},t.prototype.show=function(){this.state.isVisible||(this.focusPlease=!0,this.setState({isVisible:!0,activeLinkIndex:-1}))},t.prototype.toggleVisibility=function(){this.state.isVisible?this.hide():this.show()},t.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})},t.prototype.followActiveLink=function(){this.activeLinkAction&&this.activeLinkAction()},t.prototype.updateResults=function(){var e=this.input&&this.input.value||"",t={};this.state.fuse.search(e).forEach(function(e){var n=e.item.module;(t[n]||(t[n]=[])).push(e)});var n=[];for(var o in t)!function(e){var o=t[e],r=0;o.forEach(function(e){r+=1/e.score}),n.push({module:e,totalScore:1/r,items:o})}(o);n.sort(function(e,t){return e.totalScore-t.totalScore}),this.setState({searchString:e,isVisible:!0,moduleResults:n})},t.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},t.prototype.componentDidMount=function(){this.props.showHideTrigger(this.toggleVisibility.bind(this))},t.prototype.render=function(e,t){var n=this;if(t.failedLoading){var o="file:"==window.location.protocol;return d("div",{id:"search",class:t.isVisible?"":"hidden"},d("div",{id:"search-results"},d("p",{class:"error"},"Failed to load file 'doc-index.json' containing definitions in this package."),o?d("p",{class:"error"},"To use quick jump, load this page with HTTP (from a local static file web server) instead of using the ",d("code",null,"file://")," protocol. (For security reasons, it is not possible to fetch auxiliary files using JS in a HTML page opened with ",d("code",null,"file://"),".)"):[]))}this.linkIndex=0;var r=function(e){e.stopPropagation()},c=i(10,t.moduleResults).map(function(e){return n.renderResultsInModule(e)});return d("div",{id:"search",class:t.isVisible?"":"hidden"},d("div",{id:"search-form",onMouseDown:r},d("input",{placeholder:"Search in package by name",ref:function(e){n.input=e},onFocus:this.show.bind(this),onClick:this.show.bind(this),onInput:this.updateResults.bind(this)})),d("div",{id:"search-results",ref:function(e){n.searchResults=e},onMouseDown:r,onMouseOver:function(e){for(var t=e.target;t&&"function"==typeof t.getAttribute;){var o=t.getAttribute("data-link-index");if("string"==typeof o){var r=parseInt(o,10);n.setState({activeLinkIndex:r});break}t=t.parentNode}}},""===t.searchString?[d(a,null),d(s,null)]:0==c.length?d(l,{searchString:t.searchString}):d("ul",null,c)))},t.prototype.renderResultsInModule=function(e){var t=this,n=e.items,o=e.module,r=this.state.expanded[o]||n.length<=10,s=r?n:i(8,n),a=function(e){return d("li",{class:"search-result"},t.navigationLink(t.props.baseUrl+"/"+e.link,{},d(g,{html:e.display_html})))};return d("li",{class:"search-module"},d("h4",null,o),d("ul",null,s.map(function(e){return a(e.item)}),r?[]:d("li",{class:"more-results"},this.actionLink(function(){var e=Object.assign({},t.state.expanded);e[o]=!0,t.setState({expanded:e})},{},"show "+(n.length-s.length)+" more results from this module"))))},t.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))},t.prototype.actionLink=function(e,t){for(var n=[],o=2;o<arguments.length;o++)n[o-2]=arguments[o];var r=Object.assign({href:"#",onClick:function(t){t.preventDefault(),e()}},t);return this.menuLink.apply(this,[r,e].concat(n))},t.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,d.apply(void 0,["a",s].concat(o))},t}(f),g=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return u(t,e),t.prototype.shouldComponentUpdate=function(e){return this.props.html!==e.html},t.prototype.render=function(e){return d("div",{dangerouslySetInnerHTML:{__html:e.html}})},t}(f);n.init=c,window.quickNav={init:c}},{"fuse.js":2,preact:3}],2:[function(e,t,n){!function(e,o){"object"==typeof n&&"object"==typeof t?t.exports=o():"function"==typeof define&&define.amd?define("Fuse",[],o):"object"==typeof n?n.Fuse=o():e.Fuse=o()}(this,function(){return function(e){function t(o){if(n[o])return n[o].exports;var r=n[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,t),r.l=!0,r.exports}var n={};return t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,o){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:o})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=8)}([function(e,t,n){"use strict";e.exports=function(e){return"[object Array]"===Object.prototype.toString.call(e)}},function(e,t,n){"use strict";function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var r=function(){function e(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(t,n,o){return n&&e(t.prototype,n),o&&e(t,o),t}}(),i=n(5),s=n(7),a=n(4),l=function(){function e(t,n){var r=n.location,i=void 0===r?0:r,s=n.distance,l=void 0===s?100:s,c=n.threshold,u=void 0===c?.6:c,h=n.maxPatternLength,p=void 0===h?32:h,d=n.isCaseSensitive,f=void 0!==d&&d,v=n.tokenSeparator,_=void 0===v?/ +/g:v,g=n.findAllMatches,m=void 0!==g&&g,y=n.minMatchCharLength,k=void 0===y?1:y;o(this,e),this.options={location:i,distance:l,threshold:u,maxPatternLength:p,isCaseSensitive:f,tokenSeparator:_,findAllMatches:m,minMatchCharLength:k},this.pattern=this.options.isCaseSensitive?t:t.toLowerCase(),this.pattern.length<=p&&(this.patternAlphabet=a(this.pattern))}return r(e,[{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 i(e,this.pattern,o);var r=this.options,a=r.location,l=r.distance,c=r.threshold,u=r.findAllMatches,h=r.minMatchCharLength;return s(e,this.pattern,this.patternAlphabet,{location:a,distance:l,threshold:c,findAllMatches:u,minMatchCharLength:h})}}]),e}();e.exports=l},function(e,t,n){"use strict";var o=n(0),r=function e(t,n,r){if(n){var i=n.indexOf("."),s=n,a=null;-1!==i&&(s=n.slice(0,i),a=n.slice(i+1));var l=t[s];if(null!==l&&void 0!==l)if(a||"string"!=typeof l&&"number"!=typeof l)if(o(l))for(var c=0,u=l.length;c<u;c+=1)e(l[c],a,r);else a&&e(l,a,r);else r.push(l.toString())}else r.push(t);return r};e.exports=function(e,t){return r(e,t,[])}},function(e,t,n){"use strict";e.exports=function(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1&&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||((r=i-1)-o+1>=t&&n.push([o,r]),o=-1)}return e[i-1]&&i-o>=t&&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 o=/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g;e.exports=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:/ +/g,r=new RegExp(t.replace(o,"\\$&").replace(n,"|")),i=e.match(r),s=!!i,a=[];if(s)for(var l=0,c=i.length;l<c;l+=1){var u=i[l];a.push([e.indexOf(u),u.length-1])}return{score:s?.5:1,isMatch:s,matchedIndices:a}}},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 o=n(6),r=n(3);e.exports=function(e,t,n,i){for(var s=i.location,a=void 0===s?0:s,l=i.distance,c=void 0===l?100:l,u=i.threshold,h=void 0===u?.6:u,p=i.findAllMatches,d=void 0!==p&&p,f=i.minMatchCharLength,v=void 0===f?1:f,_=a,g=e.length,m=h,y=e.indexOf(t,_),k=t.length,b=[],x=0;x<g;x+=1)b[x]=0;if(-1!==y){var w=o(t,{errors:0,currentLocation:y,expectedLocation:_,distance:c});if(m=Math.min(w,m),-1!==(y=e.lastIndexOf(t,_+k))){var S=o(t,{errors:0,currentLocation:y,expectedLocation:_,distance:c});m=Math.min(S,m)}}y=-1;for(var L=[],C=1,M=k+g,N=1<<k-1,I=0;I<k;I+=1){for(var A=0,T=M;A<T;)o(t,{errors:I,currentLocation:_+T,expectedLocation:_,distance:c})<=m?A=T:M=T,T=Math.floor((M-A)/2+A);M=T;var O=Math.max(1,_-T+1),j=d?g:Math.min(_+T,g)+k,P=Array(j+2);P[j+1]=(1<<I)-1;for(var E=j;E>=O;E-=1){var R=E-1,U=n[e.charAt(R)];if(U&&(b[R]=1),P[E]=(P[E+1]<<1|1)&U,0!==I&&(P[E]|=(L[E+1]|L[E])<<1|1|L[E+1]),P[E]&N&&(C=o(t,{errors:I,currentLocation:R,expectedLocation:_,distance:c}))<=m){if(m=C,(y=R)<=_)break;O=Math.max(1,2*_-y)}}if(o(t,{errors:I+1,currentLocation:_,expectedLocation:_,distance:c})>m)break;L=P}return{isMatch:y>=0,score:0===C?.001:C,matchedIndices:r(b,v)}}},function(e,t,n){"use strict";function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var r=function(){function e(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(t,n,o){return n&&e(t.prototype,n),o&&e(t,o),t}}(),i=n(1),s=n(2),a=n(0),l=function(){function e(t,n){var r=n.location,i=void 0===r?0:r,a=n.distance,l=void 0===a?100:a,c=n.threshold,u=void 0===c?.6:c,h=n.maxPatternLength,p=void 0===h?32:h,d=n.caseSensitive,f=void 0!==d&&d,v=n.tokenSeparator,_=void 0===v?/ +/g:v,g=n.findAllMatches,m=void 0!==g&&g,y=n.minMatchCharLength,k=void 0===y?1:y,b=n.id,x=void 0===b?null:b,w=n.keys,S=void 0===w?[]:w,L=n.shouldSort,C=void 0===L||L,M=n.getFn,N=void 0===M?s:M,I=n.sortFn,A=void 0===I?function(e,t){return e.score-t.score}:I,T=n.tokenize,O=void 0!==T&&T,j=n.matchAllTokens,P=void 0!==j&&j,E=n.includeMatches,R=void 0!==E&&E,U=n.includeScore,D=void 0!==U&&U,V=n.verbose,F=void 0!==V&&V;o(this,e),this.options={location:i,distance:l,threshold:u,maxPatternLength:p,isCaseSensitive:f,tokenSeparator:_,findAllMatches:m,minMatchCharLength:k,id:x,keys:S,includeMatches:R,includeScore:D,shouldSort:C,getFn:N,sortFn:A,verbose:F,tokenize:O,matchAllTokens:P},this.setCollection(t)}return r(e,[{key:"setCollection",value:function(e){return this.list=e,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=arguments.length>0&&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=arguments.length>0&&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||d.weight>1)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,l=e.index,c=t.tokenSearchers,u=void 0===c?[]:c,h=t.fullSearcher,p=void 0===h?[]:h,d=t.resultMap,f=void 0===d?{}:d,v=t.results,_=void 0===v?[]:v;if(void 0!==i&&null!==i){var g=!1,m=-1,y=0;if("string"==typeof i){this._log("\nKey: "+(""===n?"-":n));var k=p.search(i);if(this._log('Full text: "'+i+'", score: '+k.score),this.options.tokenize){for(var b=i.split(this.options.tokenSeparator),x=[],w=0;w<u.length;w+=1){var S=u[w];this._log('\nPattern: "'+S.pattern+'"');for(var L=!1,C=0;C<b.length;C+=1){var M=b[C],N=S.search(M),I={};N.isMatch?(I[M]=N.score,g=!0,L=!0,x.push(N.score)):(I[M]=1,this.options.matchAllTokens||x.push(1)),this._log('Token: "'+M+'", score: '+I[M])}L&&(y+=1)}m=x[0];for(var A=x.length,T=1;T<A;T+=1)m+=x[T];m/=A,this._log("Token score average:",m)}var O=k.score;m>-1&&(O=(O+m)/2),this._log("Score average:",O);var j=!this.options.tokenize||!this.options.matchAllTokens||y>=u.length;if(this._log("\nCheck Matches: "+j),(g||k.isMatch)&&j){var P=f[l];P?P.output.push({key:n,arrayIndex:r,value:i,score:O,matchedIndices:k.matchedIndices}):(f[l]={item:s,output:[{key:n,arrayIndex:r,value:i,score:O,matchedIndices:k.matchedIndices}]},_.push(f[l]))}}else if(a(i))for(var E=0,R=i.length;E<R;E+=1)this._analyze({key:n,arrayIndex:E,value:i[E],record:s,index:l},{resultMap:f,results:_,tokenSearchers:u,fullSearcher:p})}}},{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=0,a=1,l=0;l<i;l+=1){var c=r[l].score,u=e?e[r[l].key].weight:1,h=c*u;1!==u?a=Math.min(a,h):(r[l].nScore=h,s+=h)}t[n].score=1===a?s/i: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._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")&&i.arrayIndex>-1&&(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(){if(this.options.verbose){var e;(e=console).log.apply(e,arguments)}}}]),e}();e.exports=l}])})},{}],3:[function(e,t,n){!function(){"use strict";function e(){}function n(t,n){var o,r,i,s,a=T;for(s=arguments.length;s-- >2;)A.push(arguments[s]);for(n&&null!=n.children&&(A.length||A.push(n.children),delete n.children);A.length;)if((r=A.pop())&&void 0!==r.pop)for(s=r.length;s--;)A.push(r[s]);else"boolean"==typeof r&&(r=null),(i="function"!=typeof t)&&(null==r?r="":"number"==typeof r?r=String(r):"string"!=typeof r&&(i=!1)),i&&o?a[a.length-1]+=r:a===T?a=[r]:a.push(r),o=i;var l=new e;return l.nodeName=t,l.children=a,l.attributes=null==n?void 0:n,l.key=null==n?void 0:n.key,void 0!==I.vnode&&I.vnode(l),l}function o(e,t){for(var n in t)e[n]=t[n];return e}function r(e){!e.__d&&(e.__d=!0)&&1==P.push(e)&&(I.debounceRendering||O)(i)}function i(){var e,t=P;for(P=[];e=t.pop();)e.__d&&L(e)}function s(e,t,n){return"string"==typeof t||"number"==typeof t?void 0!==e.splitText:"string"==typeof t.nodeName?!e._componentConstructor&&a(e,t.nodeName):n||e._componentConstructor===t.nodeName}function a(e,t){return e.__n===t||e.nodeName.toLowerCase()===t.toLowerCase()}function l(e){var t=o({},e.attributes);t.children=e.children;var n=e.nodeName.defaultProps;if(void 0!==n)for(var r in n)void 0===t[r]&&(t[r]=n[r]);return t}function c(e,t){var n=t?document.createElementNS("http://www.w3.org/2000/svg",e):document.createElement(e);return n.__n=e,n}function u(e){var t=e.parentNode;t&&t.removeChild(e)}function h(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===j.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,d,s):e.removeEventListener(t,d,s),(e.__l||(e.__l={}))[t]=o}else if("list"!==t&&"type"!==t&&!r&&t in e)p(e,t,null==o?"":o),null!=o&&!1!==o||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 p(e,t,n){try{e[t]=n}catch(e){}}function d(e){return this.__l[e.type](I.event&&I.event(e)||e)}function f(){for(var e;e=E.pop();)I.afterMount&&I.afterMount(e),e.componentDidMount&&e.componentDidMount()}function v(e,t,n,o,r,i){R++||(U=null!=r&&void 0!==r.ownerSVGElement,D=null!=e&&!("__preactattr_"in e));var s=_(e,t,n,o,i);return r&&s.parentNode!==r&&r.appendChild(s),--R||(D=!1,i||f()),s}function _(e,t,n,o,r){var i=e,s=U;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),m(e,!0))),i.__preactattr_=!0,i;var l=t.nodeName;if("function"==typeof l)return C(e,t,n,o);if(U="svg"===l||"foreignObject"!==l&&U,l=String(l),(!e||!a(e,l))&&(i=c(l,U),e)){for(;e.firstChild;)i.appendChild(e.firstChild);e.parentNode&&e.parentNode.replaceChild(i,e),m(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!D&&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)&&g(i,p,n,o,D||null!=h.dangerouslySetInnerHTML),k(i,t.attributes,h),U=s,i}function g(e,t,n,o,r){var i,a,l,c,h,p=e.childNodes,d=[],f={},v=0,g=0,y=p.length,k=0,b=t?t.length:0;if(0!==y)for(L=0;L<y;L++){var x=p[L],w=x.__preactattr_;null!=(S=b&&w?x._component?x._component.__k:w.key:null)?(v++,f[S]=x):(w||(void 0!==x.splitText?!r||x.nodeValue.trim():r))&&(d[k++]=x)}if(0!==b)for(L=0;L<b;L++){h=null;var S=(c=t[L]).key;if(null!=S)v&&void 0!==f[S]&&(h=f[S],f[S]=void 0,v--);else if(!h&&g<k)for(i=g;i<k;i++)if(void 0!==d[i]&&s(a=d[i],c,r)){h=a,d[i]=void 0,i===k-1&&k--,i===g&&g++;break}h=_(h,c,n,o),l=p[L],h&&h!==e&&h!==l&&(null==l?e.appendChild(h):h===l.nextSibling?u(l):e.insertBefore(h,l))}if(v)for(var L in f)void 0!==f[L]&&m(f[L],!1);for(;g<=k;)void 0!==(h=d[k--])&&m(h,!1)}function m(e,t){var n=e._component;n?M(n):(null!=e.__preactattr_&&e.__preactattr_.ref&&e.__preactattr_.ref(null),!1!==t&&null!=e.__preactattr_||u(e),y(e))}function y(e){for(e=e.lastChild;e;){var t=e.previousSibling;m(e,!0),e=t}}function k(e,t,n){var o;for(o in n)t&&null!=t[o]||null==n[o]||h(e,o,n[o],n[o]=void 0,U);for(o in t)"children"===o||"innerHTML"===o||o in n&&t[o]===("value"===o||"checked"===o?e[o]:n[o])||h(e,o,n[o],n[o]=t[o],U)}function b(e){var t=e.constructor.name;(V[t]||(V[t]=[])).push(e)}function x(e,t,n){var o,r=V[e.name];if(e.prototype&&e.prototype.render?(o=new e(t,n),N.call(o,t,n)):((o=new N(t,n)).constructor=e,o.render=w),r)for(var i=r.length;i--;)if(r[i].constructor===e){o.__b=r[i].__b,r.splice(i,1);break}return o}function w(e,t,n){return this.constructor(e,n)}function S(e,t,n,o,i){e.__x||(e.__x=!0,(e.__r=t.ref)&&delete t.ref,(e.__k=t.key)&&delete t.key,!e.base||i?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===I.syncComponentUpdates&&e.base?r(e):L(e,1,i)),e.__r&&e.__r(e))}function L(e,t,n,r){if(!e.__x){var i,s,a,c=e.props,u=e.state,h=e.context,p=e.__p||c,d=e.__s||u,_=e.__c||h,g=e.base,y=e.__b,k=g||y,b=e._component,w=!1;if(g&&(e.props=p,e.state=d,e.context=_,2!==t&&e.shouldComponentUpdate&&!1===e.shouldComponentUpdate(c,u,h)?w=!0:e.componentWillUpdate&&e.componentWillUpdate(c,u,h),e.props=c,e.state=u,e.context=h),e.__p=e.__s=e.__c=e.__b=null,e.__d=!1,!w){i=e.render(c,u,h),e.getChildContext&&(h=o(o({},h),e.getChildContext()));var C,N,A=i&&i.nodeName;if("function"==typeof A){var T=l(i);(s=b)&&s.constructor===A&&T.key==s.__k?S(s,T,1,h,!1):(C=s,e._component=s=x(A,T,h),s.__b=s.__b||y,s.__u=e,S(s,T,0,h,!1),L(s,1,n,!0)),N=s.base}else a=k,(C=b)&&(a=e._component=null),(k||1===t)&&(a&&(a._component=null),N=v(a,i,h,n||!g,k&&k.parentNode,!0));if(k&&N!==k&&s!==b){var O=k.parentNode;O&&N!==O&&(O.replaceChild(N,k),C||(k._component=null,m(k,!1)))}if(C&&M(C),e.base=N,N&&!r){for(var j=e,P=e;P=P.__u;)(j=P).base=N;N._component=j,N._componentConstructor=j.constructor}}if(!g||n?E.unshift(e):w||(e.componentDidUpdate&&e.componentDidUpdate(p,d,_),I.afterUpdate&&I.afterUpdate(e)),null!=e.__h)for(;e.__h.length;)e.__h.pop().call(e);R||r||f()}}function C(e,t,n,o){for(var r=e&&e._component,i=r,s=e,a=r&&e._componentConstructor===t.nodeName,c=a,u=l(t);r&&!c&&(r=r.__u);)c=r.constructor===t.nodeName;return r&&c&&(!o||r._component)?(S(r,u,3,n,o),e=r.base):(i&&!a&&(M(i),e=s=null),r=x(t.nodeName,u,n),e&&!r.__b&&(r.__b=e,s=null),S(r,u,1,n,o),e=r.base,s&&e!==s&&(s._component=null,m(s,!1))),e}function M(e){I.beforeUnmount&&I.beforeUnmount(e);var t=e.base;e.__x=!0,e.componentWillUnmount&&e.componentWillUnmount(),e.base=null;var n=e._component;n?M(n):t&&(t.__preactattr_&&t.__preactattr_.ref&&t.__preactattr_.ref(null),e.__b=t,u(t),b(e),y(t)),e.__r&&e.__r(null)}function N(e,t){this.__d=!0,this.context=t,this.props=e,this.state=this.state||{}}var I={},A=[],T=[],O="function"==typeof Promise?Promise.resolve().then.bind(Promise.resolve()):setTimeout,j=/acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i,P=[],E=[],R=0,U=!1,D=!1,V={};o(N.prototype,{setState:function(e,t){var n=this.state;this.__s||(this.__s=o({},n)),o(n,"function"==typeof e?e(n,this.props):e),t&&(this.__h=this.__h||[]).push(t),r(this)},forceUpdate:function(e){e&&(this.__h=this.__h||[]).push(e),L(this,2)},render:function(){}});var F={h:n,createElement:n,cloneElement:function(e,t){return n(e.nodeName,o(o({},e.attributes),t),arguments.length>2?[].slice.call(arguments,2):e.children)},Component:N,render:function(e,t,n){return v(n,e,{},!1,t,!1)},rerender:i,options:I};void 0!==t?t.exports=F:self.preact=F}()},{}]},{},[1]);  //# sourceMappingURL=quick-jump.min.js.map diff --git a/haddock-api/src/Haddock.hs b/haddock-api/src/Haddock.hs index f7fa52b3..00eb50f6 100644 --- a/haddock-api/src/Haddock.hs +++ b/haddock-api/src/Haddock.hs @@ -1,5 +1,5 @@  {-# OPTIONS_GHC -Wwarn #-} -{-# LANGUAGE CPP, ScopedTypeVariables, Rank2Types #-} +{-# LANGUAGE CPP, ScopedTypeVariables, OverloadedStrings, Rank2Types #-}  {-# LANGUAGE LambdaCase #-}  -----------------------------------------------------------------------------  -- | @@ -25,7 +25,6 @@ module Haddock (    withGhc  ) where -import Data.Version  import Haddock.Backends.Xhtml  import Haddock.Backends.Xhtml.Meta  import Haddock.Backends.Xhtml.Themes (getThemes) @@ -42,7 +41,6 @@ import Haddock.Options  import Haddock.Utils  import Control.Monad hiding (forM_) -import Control.Applicative  import Data.Foldable (forM_, foldl')  import Data.Traversable (for)  import Data.List (isPrefixOf) @@ -151,7 +149,8 @@ haddockWithGhc ghc args = handleTopExceptions $ do    -- or which exits with an error or help message.    (flags, files) <- parseHaddockOpts args    shortcutFlags flags -  qual <- case qualification flags of {Left msg -> throwE msg; Right q -> return q} +  qual <- rightOrThrowE (qualification flags) +  sinceQual <- rightOrThrowE (sinceQualification flags)    -- inject dynamic-too into flags before we proceed    flags' <- ghc flags $ do @@ -184,7 +183,7 @@ haddockWithGhc ghc args = handleTopExceptions $ do            }        -- Render the interfaces. -      liftIO $ renderStep dflags flags qual packages ifaces +      liftIO $ renderStep dflags flags sinceQual qual packages ifaces      else do        when (any (`elem` [Flag_Html, Flag_Hoogle, Flag_LaTeX]) flags) $ @@ -194,7 +193,7 @@ haddockWithGhc ghc args = handleTopExceptions $ do        packages <- liftIO $ readInterfaceFiles freshNameCache (readIfaceArgs flags)        -- Render even though there are no input files (usually contents/index). -      liftIO $ renderStep dflags flags qual packages [] +      liftIO $ renderStep dflags flags sinceQual qual packages []  -- | Create warnings about potential misuse of -optghc  warnings :: [String] -> [String] @@ -228,8 +227,9 @@ readPackagesAndProcessModules flags files = do      return (packages, ifaces, homeLinks) -renderStep :: DynFlags -> [Flag] -> QualOption -> [(DocPaths, InterfaceFile)] -> [Interface] -> IO () -renderStep dflags flags qual pkgs interfaces = do +renderStep :: DynFlags -> [Flag] -> SinceQual -> QualOption +           -> [(DocPaths, InterfaceFile)] -> [Interface] -> IO () +renderStep dflags flags sinceQual nameQual pkgs interfaces = do    updateHTMLXRefs pkgs    let      ifaceFiles = map snd pkgs @@ -238,12 +238,12 @@ renderStep dflags flags qual pkgs interfaces = do        ((_, Just path), ifile) <- pkgs        iface <- ifInstalledIfaces ifile        return (instMod iface, path) -  render dflags flags qual interfaces installedIfaces extSrcMap - +  render dflags flags sinceQual nameQual interfaces installedIfaces extSrcMap  -- | Render the interfaces with whatever backend is specified in the flags. -render :: DynFlags -> [Flag] -> QualOption -> [Interface] -> [InstalledInterface] -> Map Module FilePath -> IO () -render dflags flags qual ifaces installedIfaces extSrcMap = do +render :: DynFlags -> [Flag] -> SinceQual -> QualOption -> [Interface] +       -> [InstalledInterface] -> Map Module FilePath -> IO () +render dflags flags sinceQual qual ifaces installedIfaces extSrcMap = do    let      title                = fromMaybe "" (optTitle flags) @@ -270,6 +270,10 @@ render dflags flags qual ifaces installedIfaces extSrcMap = do      pkgKey           = moduleUnitId pkgMod      pkgStr           = Just (unitIdString pkgKey)      pkgNameVer       = modulePackageInfo dflags flags pkgMod +    pkgName          = fmap (unpackFS . (\(PackageName n) -> n)) (fst pkgNameVer) +    sincePkg         = case sinceQual of +                         External -> pkgName +                         Always -> Nothing      (srcBase, srcModule, srcEntity, srcLEntity) = sourceUrls flags @@ -277,7 +281,7 @@ render dflags flags qual ifaces installedIfaces extSrcMap = do        | Flag_HyperlinkedSource `elem` flags = Just hypSrcModuleUrlFormat        | otherwise = srcModule -    srcMap = mkSrcMap $ Map.union +    srcMap = Map.union        (Map.map SrcExternal extSrcMap)        (Map.fromList [ (ifaceMod iface, SrcLocal) | iface <- ifaces ]) @@ -323,24 +327,34 @@ render dflags flags qual ifaces installedIfaces extSrcMap = do    let withQuickjump = Flag_QuickJumpIndex `elem` flags    when (Flag_GenIndex `elem` flags) $ do -    ppHtmlIndex odir title pkgStr -                themes opt_mathjax opt_contents_url sourceUrls' opt_wiki_urls -                allVisibleIfaces pretty +    withTiming (pure dflags') "ppHtmlIndex" (const ()) $ do +      _ <- {-# SCC ppHtmlIndex #-} +           ppHtmlIndex odir title pkgStr +                  themes opt_mathjax opt_contents_url sourceUrls' opt_wiki_urls +                  allVisibleIfaces pretty +      return () +      copyHtmlBits odir libDir themes withQuickjump    when (Flag_GenContents `elem` flags) $ do -    ppHtmlContents dflags' odir title pkgStr -                   themes opt_mathjax opt_index_url sourceUrls' opt_wiki_urls -                   allVisibleIfaces True prologue pretty -                   (makeContentsQual qual) +    withTiming (pure dflags') "ppHtmlContents" (const ()) $ do +      _ <- {-# SCC ppHtmlContents #-} +           ppHtmlContents dflags' odir title pkgStr +                     themes opt_mathjax opt_index_url sourceUrls' opt_wiki_urls +                     allVisibleIfaces True prologue pretty +                     sincePkg (makeContentsQual qual) +      return ()      copyHtmlBits odir libDir themes withQuickjump    when (Flag_Html `elem` flags) $ do -    ppHtml dflags' title pkgStr visibleIfaces reexportedIfaces odir -                prologue -                themes opt_mathjax sourceUrls' opt_wiki_urls -                opt_contents_url opt_index_url unicode qual -                pretty withQuickjump +    withTiming (pure dflags') "ppHtml" (const ()) $ do +      _ <- {-# SCC ppHtml #-} +           ppHtml dflags' title pkgStr visibleIfaces reexportedIfaces odir +                  prologue +                  themes opt_mathjax sourceUrls' opt_wiki_urls +                  opt_contents_url opt_index_url unicode sincePkg qual +                  pretty withQuickjump +      return ()      copyHtmlBits odir libDir themes withQuickjump      writeHaddockMeta odir withQuickjump @@ -348,7 +362,12 @@ render dflags flags qual ifaces installedIfaces extSrcMap = do    -- might want to fix that if/when these two get some work on them    when (Flag_Hoogle `elem` flags) $ do      case pkgNameVer of -      Nothing -> putStrLn . unlines $ +      (Just (PackageName pkgNameFS), Just pkgVer) -> +          let pkgNameStr | unpackFS pkgNameFS == "main" && title /= [] = title +                         | otherwise = unpackFS pkgNameFS +          in ppHoogle dflags' pkgNameStr pkgVer title (fmap _doc prologue) +               visibleIfaces odir +      _ -> putStrLn . unlines $            [ "haddock: Unable to find a package providing module "              ++ moduleNameString (moduleName pkgMod) ++ ", skipping Hoogle."            , "" @@ -356,38 +375,19 @@ render dflags flags qual ifaces installedIfaces extSrcMap = do              ++ " using the --package-name"            , "         and --package-version arguments."            ] -      Just (PackageName pkgNameFS, pkgVer) -> -          let pkgNameStr | unpackFS pkgNameFS == "main" && title /= [] = title -                         | otherwise = unpackFS pkgNameFS -          in ppHoogle dflags' pkgNameStr pkgVer title (fmap _doc prologue) -               visibleIfaces odir    when (Flag_LaTeX `elem` flags) $ do -    ppLaTeX title pkgStr visibleIfaces odir (fmap _doc prologue) opt_latex_style -                  libDir +    withTiming (pure dflags') "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 -    ppHyperlinkedSource odir libDir opt_source_css pretty srcMap ifaces - --- | From GHC 7.10, this function has a potential to crash with a --- nasty message such as @expectJust getPackageDetails@ because --- package name and versions can no longer reliably be extracted in --- all cases: if the package is not installed yet then this info is no --- longer available. The @--package-name@ and @--package-version@ --- Haddock flags allow the user to specify this information and it is --- returned here if present: if it is not present, the error will --- occur. Nasty but that's how it is for now. Potential TODO. -modulePackageInfo :: DynFlags -                  -> [Flag] -- ^ Haddock flags are checked as they may -                            -- contain the package name or version -                            -- provided by the user which we -                            -- prioritise -                  -> Module -> Maybe (PackageName, Data.Version.Version) -modulePackageInfo dflags flags modu = -    cmdline <|> pkgDb -  where -    cmdline = (,) <$> optPackageName flags <*> optPackageVersion flags -    pkgDb = (\pkg -> (packageName pkg, packageVersion pkg)) <$> lookupPackage dflags (moduleUnitId modu) +    withTiming (pure dflags') "ppHyperlinkedSource" (const ()) $ do +      _ <- {-# SCC ppHyperlinkedSource #-} +           ppHyperlinkedSource odir libDir opt_source_css pretty srcMap ifaces +      return ()  ------------------------------------------------------------------------------- @@ -400,7 +400,7 @@ readInterfaceFiles :: MonadIO m                     -> [(DocPaths, FilePath)]                     -> m [(DocPaths, InterfaceFile)]  readInterfaceFiles name_cache_accessor pairs = do -  catMaybes `liftM` mapM tryReadIface pairs +  catMaybes `liftM` mapM ({-# SCC readInterfaceFile #-} tryReadIface) pairs    where      -- try to read an interface, warn if we can't      tryReadIface (paths, file) = @@ -439,13 +439,26 @@ withGhc' libDir flags ghcActs = runGhc (Just libDir) $ do    _ <- setSessionDynFlags dynflags''    ghcActs dynflags''    where + +    -- ignore sublists of flags that start with "+RTS" and end in "-RTS" +    -- +    -- See https://github.com/haskell/haddock/issues/666 +    filterRtsFlags :: [String] -> [String] +    filterRtsFlags flgs = foldr go (const []) flgs True +      where go "-RTS" func _ = func True +            go "+RTS" func _ = func False +            go _      func False = func False +            go arg    func True = arg : func True + +      parseGhcFlags :: MonadIO m => DynFlags -> m DynFlags      parseGhcFlags dynflags = do        -- TODO: handle warnings? -      (dynflags', rest, _) <- parseDynamicFlags dynflags (map noLoc flags) +      let flags' = filterRtsFlags flags +      (dynflags', rest, _) <- parseDynamicFlags dynflags (map noLoc flags')        if not (null rest) -        then throwE ("Couldn't parse GHC options: " ++ unwords flags) +        then throwE ("Couldn't parse GHC options: " ++ unwords flags')          else return dynflags'  unsetPatternMatchWarnings :: DynFlags -> DynFlags @@ -596,10 +609,15 @@ getPrologue dflags flags =        h <- openFile filename ReadMode        hSetEncoding h utf8        str <- hGetContents h -- semi-closes the handle -      return . Just $! parseParas dflags str +      return . Just $! parseParas dflags Nothing str      _ -> throwE "multiple -p/--prologue options" +rightOrThrowE :: Either String b -> IO b +rightOrThrowE (Left msg) = throwE msg +rightOrThrowE (Right x) = pure x + +  #ifdef IN_GHC_TREE  getInTreeDir :: IO String diff --git a/haddock-api/src/Haddock/Backends/Hoogle.hs b/haddock-api/src/Haddock/Backends/Hoogle.hs index c6139f12..257a8d6d 100644 --- a/haddock-api/src/Haddock/Backends/Hoogle.hs +++ b/haddock-api/src/Haddock/Backends/Hoogle.hs @@ -128,6 +128,7 @@ ppExport dflags ExportDecl { expItemDecl    = L _ decl          f (TyClD _ d@DataDecl{})  = ppData dflags d subdocs          f (TyClD _ d@SynDecl{})   = ppSynonym dflags d          f (TyClD _ d@ClassDecl{}) = ppClass dflags d subdocs +        f (TyClD _ (FamDecl _ d)) = ppFam dflags d          f (ForD _ (ForeignImport _ name typ _)) = [pp_sig dflags [name] (hsSigType typ)]          f (ForD _ (ForeignExport _ name typ _)) = [pp_sig dflags [name] (hsSigType typ)]          f (SigD _ sig) = ppSig dflags sig ++ ppFixities @@ -140,11 +141,7 @@ ppSigWithDoc :: DynFlags -> Sig GhcRn -> [(Name, DocForDecl Name)] -> [String]  ppSigWithDoc dflags (TypeSig _ names sig) subdocs      = concatMap mkDocSig names      where -        mkDocSig n = concatMap (ppDocumentation dflags) (getDoc n) -                     ++ [pp_sig dflags names (hsSigWcType sig)] - -        getDoc :: Located Name -> [Documentation Name] -        getDoc n = maybe [] (return . fst) (lookup (unL n) subdocs) +        mkDocSig n = mkSubdoc dflags n subdocs [pp_sig dflags [n] (hsSigWcType sig)]  ppSigWithDoc _ _ _ = [] @@ -172,10 +169,14 @@ ppClass dflags decl subdocs =          ppTyFams              | null $ tcdATs decl = ""              | otherwise = (" " ++) . showSDocUnqual dflags . whereWrapper $ concat -                [ map ppr (tcdATs decl) +                [ map pprTyFam (tcdATs decl)                  , map (ppr . tyFamEqnToSyn . unLoc) (tcdATDefs decl)                  ] +        pprTyFam :: LFamilyDecl GhcRn -> SDoc +        pprTyFam (L _ at) = vcat' $ map text $ +            mkSubdoc dflags (fdLName at) subdocs (ppFam dflags at) +          whereWrapper elems = vcat'              [ text "where" <+> lbrace              , nest 4 . vcat . map (Outputable.<> semi) $ elems @@ -191,6 +192,16 @@ ppClass dflags decl subdocs =              , tcdSExt   = emptyNameSet              } +ppFam :: DynFlags -> FamilyDecl GhcRn -> [String] +ppFam dflags decl@(FamilyDecl { fdInfo = info }) +  = [out dflags decl'] +  where +    decl' = case info of +              -- We don't need to print out a closed type family's equations +              -- for Hoogle, so pretend it doesn't have any. +              ClosedTypeFamily{} -> decl { fdInfo = OpenTypeFamily } +              _                  -> decl +ppFam _ XFamilyDecl {} = panic "ppFam"  ppInstance :: DynFlags -> ClsInst -> [String]  ppInstance dflags x = @@ -213,13 +224,12 @@ ppData dflags decl@(DataDecl { tcdDataDefn = defn }) subdocs        concatMap (ppCtor dflags decl subdocs . unL) (dd_cons defn)      where -        -- GHC gives out "data Bar =", we want to delete the equals -        -- also writes data : a b, when we want data (:) a b -        showData d = unwords $ map f $ if last xs == "=" then init xs else xs +        -- GHC gives out "data Bar =", we want to delete the equals. +        -- There's no need to worry about parenthesizing infix data type names, +        -- since this Outputable instance for TyClDecl gets this right already. +        showData d = unwords $ if last xs == "=" then init xs else xs              where                  xs = words $ out dflags d -                nam = out dflags $ tyClDeclLName d -                f w = if w == nam then operator nam else w  ppData _ _ _ = panic "ppData"  -- | for constructors, and named-fields... @@ -285,6 +295,10 @@ docWith dflags header d      lines header ++ ["" | header /= "" && isJust d] ++      maybe [] (showTags . markup (markupTag dflags)) d +mkSubdoc :: DynFlags -> Located Name -> [(Name, DocForDecl Name)] -> [String] -> [String] +mkSubdoc dflags n subdocs s = concatMap (ppDocumentation dflags) getDoc ++ s + where +   getDoc = maybe [] (return . fst) (lookup (unL n) subdocs)  data Tag = TagL Char [Tags] | TagP Tags | TagPre Tags | TagInline String Tags | Str String             deriving Show @@ -328,7 +342,8 @@ markupTag dflags = Markup {    markupAName                = const $ str "",    markupProperty             = box TagPre . str,    markupExample              = box TagPre . str . unlines . map exampleToString, -  markupHeader               = \(Header l h) -> box (TagInline $ "h" ++ show l) h +  markupHeader               = \(Header l h) -> box (TagInline $ "h" ++ show l) h, +  markupTable                = \(Table _ _) -> str "TODO: table"    } diff --git a/haddock-api/src/Haddock/Backends/Hyperlinker/Ast.hs b/haddock-api/src/Haddock/Backends/Hyperlinker/Ast.hs index 56137f51..0ecf7109 100644 --- a/haddock-api/src/Haddock/Backends/Hyperlinker/Ast.hs +++ b/haddock-api/src/Haddock/Backends/Hyperlinker/Ast.hs @@ -12,6 +12,7 @@ import qualified Haddock.Syb as Syb  import Haddock.Backends.Hyperlinker.Types  import qualified GHC +import qualified SrcLoc  import qualified Outputable as GHC  import Control.Applicative @@ -52,10 +53,10 @@ type DetailsMap = Map.Map Position (Span, TokenDetails)  mkDetailsMap :: [(GHC.SrcSpan, TokenDetails)] -> DetailsMap  mkDetailsMap xs = -  Map.fromListWith select_details [ (start, (token_span, token_details)) +  Map.fromListWith select_details [ (start, (span, token_details))                                    | (ghc_span, token_details) <- xs -                                  , Just !token_span <- [ghcSrcSpanToSpan ghc_span] -                                  , let start = spStart token_span +                                  , GHC.RealSrcSpan span <- [ghc_span] +                                  , let start = SrcLoc.realSrcSpanStart span                                    ]    where      -- favour token details which appear earlier in the list @@ -63,17 +64,11 @@ mkDetailsMap xs =  lookupBySpan :: Span -> DetailsMap -> Maybe TokenDetails  lookupBySpan span details = do -  (_, (tok_span, tok_details)) <- Map.lookupLE (spStart span) details -  guard (tok_span `containsSpan` span ) +  let pos = SrcLoc.realSrcSpanStart span +  (_, (tok_span, tok_details)) <- Map.lookupLE pos details +  guard (tok_span `SrcLoc.containsSpan` span)    return tok_details -ghcSrcSpanToSpan :: GHC.SrcSpan -> Maybe Span -ghcSrcSpanToSpan (GHC.RealSrcSpan span) = -  Just (Span { spStart = Position (GHC.srcSpanStartLine span) (GHC.srcSpanStartCol span) -             , spEnd   = Position (GHC.srcSpanEndLine span) (GHC.srcSpanEndCol span) -             }) -ghcSrcSpanToSpan _ = Nothing -  enrichToken :: Token -> DetailsMap -> Maybe TokenDetails  enrichToken (Token typ _ spn) dm      | typ `elem` [TkIdentifier, TkOperator] = lookupBySpan spn dm @@ -99,9 +94,12 @@ variables =  types :: GHC.RenamedSource -> LTokenDetails  types = everythingInRenamedSource ty    where +    ty :: forall a. Data a => a -> [(GHC.SrcSpan, TokenDetails)]      ty term = case cast term of          (Just ((GHC.L sspan (GHC.HsTyVar _ _ name)) :: GHC.LHsType GHC.GhcRn)) ->              pure (sspan, RtkType (GHC.unLoc name)) +        (Just ((GHC.L sspan (GHC.HsOpTy _ l name r)) :: GHC.LHsType GHC.GhcRn)) -> +            (sspan, RtkType (GHC.unLoc name)):(ty l ++ ty r)          _ -> empty  -- | Obtain details map for identifier bindings. @@ -117,6 +115,11 @@ binds = everythingInRenamedSource      fun term = case cast term of          (Just (GHC.FunBind _ (GHC.L sspan name) _ _ _ :: GHC.HsBind GHC.GhcRn)) ->              pure (sspan, RtkBind name) +        (Just (GHC.PatSynBind _ (GHC.PSB _ (GHC.L sspan name) args _ _))) -> +            pure (sspan, RtkBind name) ++ everythingInRenamedSource patsyn_binds args +        _ -> empty +    patsyn_binds term = case cast term of +        (Just (GHC.L sspan (name :: GHC.Name))) -> pure (sspan, RtkVar name)          _ -> empty      pat term = case cast term of          (Just ((GHC.L sspan (GHC.VarPat _ name)) :: GHC.LPat GHC.GhcRn)) -> @@ -142,6 +145,7 @@ decls :: GHC.RenamedSource -> LTokenDetails  decls (group, _, _, _) = concatMap ($ group)      [ concat . map typ . concat . map GHC.group_tyclds . GHC.hs_tyclds      , everythingInRenamedSource fun . GHC.hs_valds +    , everythingInRenamedSource fix . GHC.hs_fixds      , everythingInRenamedSource (con `Syb.combine` ins)      ]    where @@ -149,11 +153,16 @@ decls (group, _, _, _) = concatMap ($ group)          GHC.DataDecl { tcdLName = name } -> pure . decl $ name          GHC.SynDecl _ name _ _ _ -> pure . decl $ name          GHC.FamDecl _ fam -> pure . decl $ GHC.fdLName fam -        GHC.ClassDecl{..} -> [decl tcdLName] ++ concatMap sig tcdSigs +        GHC.ClassDecl{..} -> +          [decl tcdLName] +            ++ concatMap sig tcdSigs +            ++ concatMap tyfam tcdATs          GHC.XTyClDecl {} -> GHC.panic "haddock:decls"      fun term = case cast term of          (Just (GHC.FunBind _ (GHC.L sspan name) _ _ _ :: GHC.HsBind GHC.GhcRn))              | GHC.isExternalName name -> pure (sspan, RtkDecl name) +        (Just (GHC.PatSynBind _ (GHC.PSB _ (GHC.L sspan name) _ _ _))) +            | GHC.isExternalName name -> pure (sspan, RtkDecl name)          _ -> empty      con term = case cast term of          (Just (cdcl :: GHC.ConDecl GHC.GhcRn)) -> @@ -171,7 +180,17 @@ decls (group, _, _, _) = concatMap ($ group)          Just (field :: GHC.ConDeclField GHC.GhcRn)            -> map (decl . fmap GHC.extFieldOcc) $ GHC.cd_fld_names field          Nothing -> empty +    fix term = case cast term of +        Just ((GHC.FixitySig _ names _) :: GHC.FixitySig GHC.GhcRn) +          -> map (\(GHC.L sspan x) -> (sspan, RtkVar x)) names +        Just ((GHC.XFixitySig {}) :: GHC.FixitySig GHC.GhcRn) +          -> GHC.panic "haddock:decls" +        Nothing -> empty +    tyfam (GHC.L _ (GHC.FamilyDecl{..})) = [decl fdLName] +    tyfam (GHC.L _ (GHC.XFamilyDecl {})) = GHC.panic "haddock:dels"      sig (GHC.L _ (GHC.TypeSig _ names _)) = map decl names +    sig (GHC.L _ (GHC.PatSynSig _ names _)) = map decl names +    sig (GHC.L _ (GHC.ClassOpSig _ _ names _)) = map decl names      sig _ = []      decl (GHC.L sspan name) = (sspan, RtkDecl name)      tyref (GHC.L sspan name) = (sspan, RtkType name) @@ -190,10 +209,11 @@ imports src@(_, imps, _, _) =          (Just (GHC.IEThingAll _ t)) -> pure $ typ $ GHC.ieLWrappedName t          (Just (GHC.IEThingWith _ t _ vs _fls)) ->            [typ $ GHC.ieLWrappedName t] ++ map (var . GHC.ieLWrappedName) vs +        (Just (GHC.IEModuleContents _ m)) -> pure $ modu m          _ -> empty      typ (GHC.L sspan name) = (sspan, RtkType name)      var (GHC.L sspan name) = (sspan, RtkVar name) -    imp idecl | not . GHC.ideclImplicit $ idecl = -        let (GHC.L sspan name) = GHC.ideclName idecl -        in Just (sspan, RtkModule name) -    imp _ = Nothing +    modu (GHC.L sspan name) = (sspan, RtkModule name) +    imp idecl +      | not . GHC.ideclImplicit $ idecl = Just (modu (GHC.ideclName idecl)) +      | otherwise = Nothing diff --git a/haddock-api/src/Haddock/Backends/Hyperlinker/Parser.hs b/haddock-api/src/Haddock/Backends/Hyperlinker/Parser.hs index e4345602..e7ecac73 100644 --- a/haddock-api/src/Haddock/Backends/Hyperlinker/Parser.hs +++ b/haddock-api/src/Haddock/Backends/Hyperlinker/Parser.hs @@ -1,11 +1,19 @@  module Haddock.Backends.Hyperlinker.Parser (parse) where +import Data.Either         ( isRight, isLeft ) +import Data.List           ( foldl', isPrefixOf, isSuffixOf ) +import Data.Maybe          ( maybeToList ) +import Data.Char           ( isSpace ) +import qualified Text.Read as R -import Data.Char -import Data.List -import Data.Maybe +import GHC                 ( DynFlags, addSourceToTokens ) +import SrcLoc +import FastString          ( mkFastString ) +import StringBuffer        ( stringToStringBuffer ) +import Lexer               ( Token(..) ) +import qualified Lexer as L -import Haddock.Backends.Hyperlinker.Types +import Haddock.Backends.Hyperlinker.Types as T  -- | Turn source code string into a stream of more descriptive tokens. @@ -13,202 +21,419 @@ import Haddock.Backends.Hyperlinker.Types  -- Result should retain original file layout (including comments, whitespace,  -- etc.), i.e. the following "law" should hold:  -- --- @concat . map 'tkValue' . 'parse' = id@ -parse :: String -> [Token] -parse = tokenize . tag . chunk +-- prop> concat . map tkValue . parse = id +-- +-- (In reality, this only holds for input not containing '\r', '\t', '\f', '\v', +-- characters, since GHC transforms those into ' ' and '\n') +parse :: DynFlags -> FilePath -> String -> [T.Token] +parse dflags fp = ghcToks . processCPP dflags fp . filterCRLF +  where +    -- Remove CRLFs from source +    filterCRLF :: String -> String +    filterCRLF ('\r':'\n':cs) = '\n' : filterCRLF cs +    filterCRLF (c:cs) = c : filterCRLF cs +    filterCRLF [] = [] --- | Split raw source string to more meaningful chunks. +-- | Parse the source into tokens using the GHC lexer.  -- --- This is the initial stage of tokenization process. Each chunk is either --- a comment (including comment delimiters), a whitespace string, preprocessor --- macro (and all its content until the end of a line) or valid Haskell lexeme. -chunk :: String -> [String] -chunk [] = [] -chunk str@(c:_) -    | isSpace c = -        let (space, mcpp, rest) = spanSpaceOrCpp str -        in [space] ++ maybeToList mcpp ++ chunk rest -chunk str -    | "--" `isPrefixOf` str = chunk' $ spanToNewline str -    | "{-" `isPrefixOf` str = chunk' $ chunkComment 0 str -    | otherwise = case lex' str of -        (tok:_) -> chunk' tok -        [] -> [str] +--   * CPP lines are removed and reinserted as line-comments +--   * top-level file pragmas are parsed as block comments (see the +--     'ITblockComment' case of 'classify' for more details) +-- +processCPP :: DynFlags    -- ^ GHC's flags +           -> FilePath    -- ^ source file name (for position information) +           -> String      -- ^ source file contents +           -> [(Located L.Token, String)] +processCPP dflags fpath s = addSrc . go start . splitCPP $ s    where -    chunk' (c, rest) = c:(chunk rest) +    start = mkRealSrcLoc (mkFastString fpath) 1 1 +    addSrc = addSourceToTokens start (stringToStringBuffer s) --- | A bit better lexer then the default, i.e. handles DataKinds quotes -lex' :: ReadS String -lex' ('\'' : '\'' : rest)              = [("''", rest)] -lex' str@('\'' : '\\' : _ : '\'' : _)  = lex str -lex' str@('\'' : _ : '\'' : _)         = lex str -lex' ('\'' : rest)                     = [("'", rest)] -lex' str                               = lex str +    -- Transform a list of Haskell/CPP lines into a list of tokens +    go :: RealSrcLoc -> [Either String String] -> [Located L.Token] +    go _   [] = [] +    go pos ls = +      let (hLinesRight,  ls')  = span isRight ls +          (cppLinesLeft, rest) = span isLeft ls' --- | Split input to "first line" string and the rest of it. --- --- Ideally, this should be done simply with @'break' (== '\n')@. However, --- Haskell also allows line-unbreaking (or whatever it is called) so things --- are not as simple and this function deals with that. -spanToNewline :: String -> (String, String) -spanToNewline [] = ([], []) -spanToNewline ('\\':'\n':str) = -    let (str', rest) = spanToNewline str -    in ('\\':'\n':str', rest) -spanToNewline str@('\n':_) = ("", str) -spanToNewline (c:str) = -    let (str', rest) = spanToNewline str -    in (c:str', rest) +          hSrc   = concat [ hLine   | Right hLine  <- hLinesRight  ] +          cppSrc = concat [ cppLine | Left cppLine <- cppLinesLeft ] + +      in case L.lexTokenStream (stringToStringBuffer hSrc) pos dflags of --- | Split input to whitespace string, (optional) preprocessor directive and --- the rest of it. +           -- Stuff that fails to lex gets turned into comments +           L.PFailed _ _ss _msg -> +             let (src_pos, failed) = mkToken ITunknown pos hSrc +                 (new_pos, cpp)    = mkToken ITlineComment src_pos cppSrc +             in failed : cpp : go new_pos rest + +           -- Successfully lexed +           L.POk ss toks -> +             let (new_pos, cpp) = mkToken ITlineComment (L.loc ss) cppSrc +             in toks ++ [cpp] ++ go new_pos rest + +    -- Manually make a token from a 'String', advancing the cursor position +    mkToken tok start' str = +      let end = foldl' advanceSrcLoc start' str +      in (end, L (RealSrcSpan $ mkRealSrcSpan start' end) (tok str)) + + +-- | Split apart the initial file into Haskell source lines ('Left' entries) and +-- CPP lines ('Right' entries).  -- --- Again, using something like @'span' 'isSpace'@ would be nice to chunk input --- to whitespace. The problem is with /#/ symbol - if it is placed at the very --- beginning of a line, it should be recognized as preprocessor macro. In any --- other case, it is ordinary Haskell symbol and can be used to declare --- operators. Hence, while dealing with whitespace we also check whether there --- happens to be /#/ symbol just after a newline character - if that is the --- case, we begin treating the whole line as preprocessor macro. -spanSpaceOrCpp :: String -> (String, Maybe String, String) -spanSpaceOrCpp ('\n':'#':str) = -    let (str', rest) = spanToNewline str -    in ("\n", Just $ '#':str', rest) -spanSpaceOrCpp (c:str') -    | isSpace c = -        let (space, mcpp, rest) = spanSpaceOrCpp str' -        in (c:space, mcpp, rest) -spanSpaceOrCpp str = ("", Nothing, str) - --- | Split input to comment content (including delimiters) and the rest. +-- All characters in the input are present in the output:  -- --- Again, some more logic than simple 'span' is required because of Haskell --- comment nesting policy. -chunkComment :: Int -> String -> (String, String) -chunkComment _ [] = ("", "") -chunkComment depth ('{':'-':str) = -    let (c, rest) = chunkComment (depth + 1) str -    in ("{-" ++ c, rest) -chunkComment depth ('-':'}':str) -    | depth == 1 = ("-}", str) -    | otherwise = -        let (c, rest) = chunkComment (depth - 1) str -        in ("-}" ++ c, rest) -chunkComment depth (e:str) = -    let (c, rest) = chunkComment depth str -    in (e:c, rest) - --- | Assign source location for each chunk in given stream. -tag :: [String] -> [(Span, String)] -tag = -    reverse . snd . foldl aux (Position 1 1, []) +-- prop> concat . map (either id id) . splitCPP = id +splitCPP :: String -> [Either String String] +splitCPP "" = [] +splitCPP s | isCPPline s = Left l : splitCPP rest +           | otherwise =  Right l : splitCPP rest    where -    aux (pos, cs) str = -        let pos' = foldl move pos str -        in (pos', (Span pos pos', str):cs) -    move pos '\n' = pos { posRow = posRow pos + 1, posCol = 1 } -    move pos _ = pos { posCol = posCol pos + 1 } - --- | Turn unrecognised chunk stream to more descriptive token stream. -tokenize :: [(Span, String)] -> [Token] -tokenize = -    map aux -  where -    aux (sp, str) = Token -        { tkType = classify str -        , tkValue = str -        , tkSpan = sp -        } +    ~(l, rest) = spanToNewline 0 s + --- | Classify given string as appropriate Haskell token. +-- | Heuristic to decide if a line is going to be a CPP line. This should be a +-- cheap operation since it is going to be run on every line being processed. +-- +-- Right now it just checks if the first non-whitespace character in the first +-- five characters of the line is a '#':  -- --- This method is based on Haskell 98 Report lexical structure description: --- https://www.haskell.org/onlinereport/lexemes.html +-- >>> isCPPline "#define FOO 1" +-- True  -- --- However, this is probably far from being perfect and most probably does not --- handle correctly all corner cases. -classify :: String -> TokenType -classify str -    | "--" `isPrefixOf` str = TkComment -    | "{-#" `isPrefixOf` str = TkPragma -    | "{-" `isPrefixOf` str = TkComment -classify "''" = TkSpecial -classify "'"  = TkSpecial -classify str@(c:_) -    | isSpace c = TkSpace -    | isDigit c = TkNumber -    | c `elem` special = TkSpecial -    | str `elem` glyphs = TkGlyph -    | all (`elem` symbols) str = TkOperator -    | c == '#' = TkCpp -    | c == '"' = TkString -    | c == '\'' = TkChar -classify str -    | str `elem` keywords = TkKeyword -    | isIdentifier str = TkIdentifier -    | otherwise = TkUnknown - -keywords :: [String] -keywords = -    [ "as" -    , "case" -    , "class" -    , "data" -    , "default" -    , "deriving" -    , "do" -    , "else" -    , "hiding" -    , "if" -    , "import" -    , "in" -    , "infix" -    , "infixl" -    , "infixr" -    , "instance" -    , "let" -    , "module" -    , "newtype" -    , "of" -    , "qualified" -    , "then" -    , "type" -    , "where" -    , "forall" -    , "family" -    , "mdo" -    ] - -glyphs :: [String] -glyphs = -    [ ".." -    , ":" -    , "::" -    , "=" -    , "\\" -    , "|" -    , "<-" -    , "->" -    , "@" -    , "~" -    , "~#" -    , "=>" -    , "-" -    , "!" -    ] - -special :: [Char] -special = "()[]{},;`" - --- TODO: Add support for any Unicode symbol or punctuation. --- source: http://stackoverflow.com/questions/10548170/what-characters-are-permitted-for-haskell-operators -symbols :: [Char] -symbols = "!#$%&*+./<=>?@\\^|-~:" - -isIdentifier :: String -> Bool -isIdentifier (s:str) -    | (isLower' s || isUpper s) && all isAlphaNum' str = True +-- >>> isCPPline "\t\t  #ifdef GHC" +-- True +-- +-- >>> isCPPline "       #endif" +-- False +-- +isCPPline :: String -> Bool +isCPPline = isPrefixOf "#" . dropWhile (`elem` " \t") . take 5 + + +-- | Split a "line" off the front of a string, hopefully without cutting tokens +-- in half. I say "hopefully" because knowing what a token is requires lexing, +-- yet lexing depends on this function. +-- +-- All characters in the input are present in the output: +-- +-- prop> curry (++) . spanToNewLine 0 = id +spanToNewline :: Int                 -- ^ open '{-' +              -> String              -- ^ input +              -> (String, String) + +-- Base case and space characters +spanToNewline _ "" = ("", "") +spanToNewline n ('\n':str) | n <= 0 = ("\n", str) +spanToNewline n ('\n':str) | n <= 0 = ("\n", str) +spanToNewline n ('\\':'\n':str) = +    let (str', rest) = spanToNewline n str +    in ('\\':'\n':str', rest) + +-- Block comments +spanToNewline n ('{':'-':str) = +    let (str', rest) = spanToNewline (n+1) str +    in ('{':'-':str', rest) +spanToNewline n ('-':'}':str) = +    let (str', rest) = spanToNewline (n-1) str +    in ('-':'}':str', rest) + +-- When not in a block comment, try to lex a Haskell token +spanToNewline 0 str@(c:_) | ((lexed, str') : _) <- R.lex str, not (isSpace c) = +    if all (== '-') lexed && length lexed >= 2 +      -- A Haskell line comment +      then case span (/= '\n') str' of +             (str'', '\n':rest) -> (lexed ++ str'' ++ "\n", rest) +             (_, _) -> (str, "")  + +      -- An actual Haskell token +      else let (str'', rest) = spanToNewline 0 str' +           in (lexed ++ str'', rest) + +-- In all other cases, advance one character at a time +spanToNewline n (c:str) = +    let (str', rest) = spanToNewline n str +    in (c:str', rest) + + +-- | Turn a list of GHC's 'L.Token' (and their source 'String') into a list of +-- Haddock's 'T.Token'. +ghcToks :: [(Located L.Token, String)] -> [T.Token] +ghcToks = reverse . (\(_,ts,_) -> ts) . foldl' go (start, [], False)    where -    isLower' c = isLower c || c == '_' -    isAlphaNum' c = isAlphaNum c || c == '_' || c == '\'' -isIdentifier _ = False +    start = mkRealSrcLoc (mkFastString "lexing") 1 1 + +    go :: (RealSrcLoc, [T.Token], Bool) +       -- ^ current position, tokens accumulated, currently in pragma (or not) +        +       -> (Located L.Token, String) +       -- ^ next token, its content +        +       -> (RealSrcLoc, [T.Token], Bool) +       -- ^ new position, new tokens accumulated, currently in pragma (or not) + +    go (pos, toks, in_prag) (L l tok, raw) = +        ( next_pos +        , classifiedTok ++ maybeToList white ++ toks +        , inPragma in_prag tok +        ) +       where +         (next_pos, white) = mkWhitespace pos l +          +         classifiedTok = [ Token (classify' tok) raw rss +                         | RealSrcSpan rss <- [l] +                         , not (null raw) +                         ] +          +         classify' | in_prag = const TkPragma +                   | otherwise = classify + + +-- | Find the correct amount of whitespace between tokens. +mkWhitespace :: RealSrcLoc -> SrcSpan -> (RealSrcLoc, Maybe T.Token) +mkWhitespace prev spn = +  case spn of +    UnhelpfulSpan _ -> (prev,Nothing) +    RealSrcSpan s | null wsstring -> (end, Nothing) +                  | otherwise -> (end, Just (Token TkSpace wsstring wsspan)) +      where +        start = realSrcSpanStart s +        end = realSrcSpanEnd s +        wsspan = mkRealSrcSpan prev start +        nls = srcLocLine start - srcLocLine prev +        spaces = if nls == 0 then srcLocCol start - srcLocCol prev +                             else srcLocCol start - 1 +        wsstring = replicate nls '\n' ++ replicate spaces ' ' + + +-- | Classify given tokens as appropriate Haskell token type. +classify :: L.Token -> TokenType +classify tok = +  case tok of +    ITas                   -> TkKeyword +    ITcase                 -> TkKeyword +    ITclass                -> TkKeyword +    ITdata                 -> TkKeyword +    ITdefault              -> TkKeyword +    ITderiving             -> TkKeyword +    ITdo                   -> TkKeyword +    ITelse                 -> TkKeyword +    IThiding               -> TkKeyword +    ITforeign              -> TkKeyword +    ITif                   -> TkKeyword +    ITimport               -> TkKeyword +    ITin                   -> TkKeyword +    ITinfix                -> TkKeyword +    ITinfixl               -> TkKeyword +    ITinfixr               -> TkKeyword +    ITinstance             -> TkKeyword +    ITlet                  -> TkKeyword +    ITmodule               -> TkKeyword +    ITnewtype              -> TkKeyword +    ITof                   -> TkKeyword +    ITqualified            -> TkKeyword +    ITthen                 -> TkKeyword +    ITtype                 -> TkKeyword +    ITvia                  -> TkKeyword +    ITwhere                -> TkKeyword + +    ITforall            {} -> TkKeyword +    ITexport               -> TkKeyword +    ITlabel                -> TkKeyword +    ITdynamic              -> TkKeyword +    ITsafe                 -> TkKeyword +    ITinterruptible        -> TkKeyword +    ITunsafe               -> TkKeyword +    ITstdcallconv          -> TkKeyword +    ITccallconv            -> TkKeyword +    ITcapiconv             -> TkKeyword +    ITprimcallconv         -> TkKeyword +    ITjavascriptcallconv   -> TkKeyword +    ITmdo                  -> TkKeyword +    ITfamily               -> TkKeyword +    ITrole                 -> TkKeyword +    ITgroup                -> TkKeyword +    ITby                   -> TkKeyword +    ITusing                -> TkKeyword +    ITpattern              -> TkKeyword +    ITstatic               -> TkKeyword +    ITstock                -> TkKeyword +    ITanyclass             -> TkKeyword + +    ITunit                 -> TkKeyword +    ITsignature            -> TkKeyword +    ITdependency           -> TkKeyword +    ITrequires             -> TkKeyword + +    ITinline_prag       {} -> TkPragma +    ITspec_prag         {} -> TkPragma +    ITspec_inline_prag  {} -> TkPragma +    ITsource_prag       {} -> TkPragma +    ITrules_prag        {} -> TkPragma +    ITwarning_prag      {} -> TkPragma +    ITdeprecated_prag   {} -> TkPragma +    ITline_prag         {} -> TkPragma +    ITcolumn_prag       {} -> TkPragma +    ITscc_prag          {} -> TkPragma +    ITgenerated_prag    {} -> TkPragma +    ITcore_prag         {} -> TkPragma +    ITunpack_prag       {} -> TkPragma +    ITnounpack_prag     {} -> TkPragma +    ITann_prag          {} -> TkPragma +    ITcomplete_prag     {} -> TkPragma +    ITclose_prag           -> TkPragma +    IToptions_prag      {} -> TkPragma +    ITinclude_prag      {} -> TkPragma +    ITlanguage_prag        -> TkPragma +    ITminimal_prag      {} -> TkPragma +    IToverlappable_prag {} -> TkPragma +    IToverlapping_prag  {} -> TkPragma +    IToverlaps_prag     {} -> TkPragma +    ITincoherent_prag   {} -> TkPragma +    ITctype             {} -> TkPragma + +    ITdotdot               -> TkGlyph +    ITcolon                -> TkGlyph +    ITdcolon            {} -> TkGlyph +    ITequal                -> TkGlyph +    ITlam                  -> TkGlyph +    ITlcase                -> TkGlyph +    ITvbar                 -> TkGlyph +    ITlarrow            {} -> TkGlyph +    ITrarrow            {} -> TkGlyph +    ITat                   -> TkGlyph +    ITtilde                -> TkGlyph +    ITdarrow            {} -> TkGlyph +    ITminus                -> TkGlyph +    ITbang                 -> TkGlyph +    ITdot                  -> TkOperator +    ITtypeApp              -> TkGlyph + +    ITbiglam               -> TkGlyph + +    ITocurly               -> TkSpecial +    ITccurly               -> TkSpecial +    ITvocurly              -> TkSpecial +    ITvccurly              -> TkSpecial +    ITobrack               -> TkSpecial +    ITopabrack             -> TkSpecial +    ITcpabrack             -> TkSpecial +    ITcbrack               -> TkSpecial +    IToparen               -> TkSpecial +    ITcparen               -> TkSpecial +    IToubxparen            -> TkSpecial +    ITcubxparen            -> TkSpecial +    ITsemi                 -> TkSpecial +    ITcomma                -> TkSpecial +    ITunderscore           -> TkIdentifier +    ITbackquote            -> TkSpecial +    ITsimpleQuote          -> TkSpecial + +    ITvarid             {} -> TkIdentifier +    ITconid             {} -> TkIdentifier +    ITvarsym            {} -> TkOperator +    ITconsym            {} -> TkOperator +    ITqvarid            {} -> TkIdentifier +    ITqconid            {} -> TkIdentifier +    ITqvarsym           {} -> TkOperator +    ITqconsym           {} -> TkOperator + +    ITdupipvarid        {} -> TkUnknown +    ITlabelvarid        {} -> TkUnknown + +    ITchar              {} -> TkChar +    ITstring            {} -> TkString +    ITinteger           {} -> TkNumber +    ITrational          {} -> TkNumber + +    ITprimchar          {} -> TkChar +    ITprimstring        {} -> TkString +    ITprimint           {} -> TkNumber +    ITprimword          {} -> TkNumber +    ITprimfloat         {} -> TkNumber +    ITprimdouble        {} -> TkNumber + +    ITopenExpQuote      {} -> TkSpecial +    ITopenPatQuote         -> TkSpecial +    ITopenDecQuote         -> TkSpecial +    ITopenTypQuote         -> TkSpecial +    ITcloseQuote        {} -> TkSpecial +    ITopenTExpQuote     {} -> TkSpecial +    ITcloseTExpQuote       -> TkSpecial +    ITidEscape          {} -> TkUnknown +    ITparenEscape          -> TkSpecial +    ITidTyEscape        {} -> TkUnknown +    ITparenTyEscape        -> TkSpecial +    ITtyQuote              -> TkSpecial +    ITquasiQuote        {} -> TkUnknown +    ITqQuasiQuote       {} -> TkUnknown + +    ITproc                 -> TkKeyword +    ITrec                  -> TkKeyword +    IToparenbar         {} -> TkGlyph +    ITcparenbar         {} -> TkGlyph +    ITlarrowtail        {} -> TkGlyph +    ITrarrowtail        {} -> TkGlyph +    ITLarrowtail        {} -> TkGlyph +    ITRarrowtail        {} -> TkGlyph + +    ITunknown           {} -> TkUnknown +    ITeof                  -> TkUnknown + +    -- Line comments are only supposed to start with '--'. Starting with '#' +    -- means that this was probably a CPP. +    ITlineComment s +      | isCPPline s        -> TkCpp +      | otherwise          -> TkComment + +    ITdocCommentNext    {} -> TkComment +    ITdocCommentPrev    {} -> TkComment +    ITdocCommentNamed   {} -> TkComment +    ITdocSection        {} -> TkComment +    ITdocOptions        {} -> TkComment + +    -- The lexer considers top-level pragmas as comments (see `pragState` in +    -- the GHC lexer for more), so we have to manually reverse this. The +    -- following is a hammer: it smashes _all_ pragma-like block comments into +    -- pragmas. +    ITblockComment c +      | isPrefixOf "{-#" c +      , isSuffixOf "#-}" c -> TkPragma +      | otherwise          -> TkComment + +-- | Classify given tokens as beginning pragmas (or not). +inPragma :: Bool     -- ^ currently in pragma +         -> L.Token  -- ^ current token +         -> Bool     -- ^ new information about whether we are in a pragma +inPragma _ ITclose_prag = False +inPragma True _ = True +inPragma False tok = +  case tok of +    ITinline_prag       {} -> True +    ITspec_prag         {} -> True +    ITspec_inline_prag  {} -> True +    ITsource_prag       {} -> True +    ITrules_prag        {} -> True +    ITwarning_prag      {} -> True +    ITdeprecated_prag   {} -> True +    ITline_prag         {} -> True +    ITcolumn_prag       {} -> True +    ITscc_prag          {} -> True +    ITgenerated_prag    {} -> True +    ITcore_prag         {} -> True +    ITunpack_prag       {} -> True +    ITnounpack_prag     {} -> True +    ITann_prag          {} -> True +    ITcomplete_prag     {} -> True +    IToptions_prag      {} -> True +    ITinclude_prag      {} -> True +    ITlanguage_prag        -> True +    ITminimal_prag      {} -> True +    IToverlappable_prag {} -> True +    IToverlapping_prag  {} -> True +    IToverlaps_prag     {} -> True +    ITincoherent_prag   {} -> True +    ITctype             {} -> True + +    _                      -> False + diff --git a/haddock-api/src/Haddock/Backends/Hyperlinker/Renderer.hs b/haddock-api/src/Haddock/Backends/Hyperlinker/Renderer.hs index 15793f0c..d7ea70a6 100644 --- a/haddock-api/src/Haddock/Backends/Hyperlinker/Renderer.hs +++ b/haddock-api/src/Haddock/Backends/Hyperlinker/Renderer.hs @@ -1,6 +1,5 @@  {-# LANGUAGE RecordWildCards #-} -  module Haddock.Backends.Hyperlinker.Renderer (render) where @@ -15,7 +14,6 @@ import System.FilePath.Posix ((</>))  import Data.List  import Data.Maybe -import Data.Monoid  import qualified Data.Map as Map  import Text.XHtml (Html, HtmlAttr, (!)) @@ -29,36 +27,10 @@ render :: Maybe FilePath -> Maybe FilePath -> SrcMap -> [RichToken]         -> Html  render mcss mjs srcs tokens = header mcss mjs <> body srcs tokens - -data TokenGroup -    = GrpNormal Token -    | GrpRich TokenDetails [Token] - - --- | Group consecutive tokens pointing to the same element. --- --- We want to render qualified identifiers as one entity. For example, --- @Bar.Baz.foo@ consists of 5 tokens (@Bar@, @.@, @Baz@, @.@, @foo@) but for --- better user experience when highlighting and clicking links, these tokens --- should be regarded as one identifier. Therefore, before rendering we must --- group consecutive elements pointing to the same 'GHC.Name' (note that even --- dot token has it if it is part of qualified name). -groupTokens :: [RichToken] -> [TokenGroup] -groupTokens [] = [] -groupTokens ((RichToken tok Nothing):rest) = (GrpNormal tok):(groupTokens rest) -groupTokens ((RichToken tok (Just det)):rest) = -    let (grp, rest') = span same rest -    in (GrpRich det (tok:(map rtkToken grp))):(groupTokens rest') -  where -    same (RichToken _ (Just det')) = det == det' -    same _ = False - -  body :: SrcMap -> [RichToken] -> Html -body srcs tokens = -    Html.body . Html.pre $ hypsrc +body srcs tokens = Html.body . Html.pre $ hypsrc    where -    hypsrc = mconcat . map (tokenGroup srcs) . groupTokens $ tokens +    hypsrc = mconcat . map (richToken srcs) $ tokens  header :: Maybe FilePath -> Maybe FilePath -> Html @@ -79,29 +51,20 @@ header mcss mjs =          , Html.src scriptFile          ] - -tokenGroup :: SrcMap -> TokenGroup -> Html -tokenGroup _ (GrpNormal tok@(Token { .. })) -    | tkType == TkSpace = renderSpace (posRow . spStart $ tkSpan) tkValue -    | otherwise = tokenSpan tok ! attrs +-- | Given information about the source position of definitions, render a token +richToken :: SrcMap -> RichToken -> Html +richToken srcs (RichToken Token{..} details) +    | tkType == TkSpace = renderSpace (GHC.srcSpanStartLine tkSpan) tkValue +    | otherwise = linked content    where -    attrs = [ multiclass . tokenStyle $ tkType ] -tokenGroup srcs (GrpRich det tokens) = -    externalAnchor det . internalAnchor det . hyperlink srcs det $ content -  where -    content = mconcat . map (richToken det) $ tokens - - -richToken :: TokenDetails -> Token -> Html -richToken det tok = -    tokenSpan tok ! [ multiclass style ] -  where -    style = (tokenStyle . tkType) tok ++ richTokenStyle det - - -tokenSpan :: Token -> Html -tokenSpan = Html.thespan . Html.toHtml . tkValue +    content = tokenSpan ! [ multiclass style ] +    tokenSpan = Html.thespan (Html.toHtml tkValue) +    style = tokenStyle tkType ++ maybe [] richTokenStyle details +    -- If we have name information, we can make links +    linked = case details of +      Just d -> externalAnchor d . internalAnchor d . hyperlink srcs d +      Nothing -> id  richTokenStyle :: TokenDetails -> [StyleClass]  richTokenStyle (RtkVar _) = ["hs-var"] @@ -155,7 +118,7 @@ internalHyperlink name content =      Html.anchor content ! [ Html.href $ "#" ++ internalAnchorIdent name ]  externalNameHyperlink :: SrcMap -> GHC.Name -> Html -> Html -externalNameHyperlink (srcs, _) name content = case Map.lookup mdl srcs of +externalNameHyperlink srcs name content = case Map.lookup mdl srcs of      Just SrcLocal -> Html.anchor content !          [ Html.href $ hypSrcModuleNameUrl mdl name ]      Just (SrcExternal path) -> Html.anchor content ! @@ -165,12 +128,14 @@ externalNameHyperlink (srcs, _) name content = case Map.lookup mdl srcs of      mdl = GHC.nameModule name  externalModHyperlink :: SrcMap -> GHC.ModuleName -> Html -> Html -externalModHyperlink (_, srcs) name content = case Map.lookup name srcs of -    Just SrcLocal -> Html.anchor content ! +externalModHyperlink srcs name content = +    let srcs' = Map.mapKeys GHC.moduleName srcs in +    case Map.lookup name srcs' of +      Just SrcLocal -> Html.anchor content !          [ Html.href $ hypSrcModuleUrl' name ] -    Just (SrcExternal path) -> Html.anchor content ! +      Just (SrcExternal path) -> Html.anchor content !          [ Html.href $ path </> hypSrcModuleUrl' name ] -    Nothing -> content +      Nothing -> content  renderSpace :: Int -> String -> Html diff --git a/haddock-api/src/Haddock/Backends/Hyperlinker/Types.hs b/haddock-api/src/Haddock/Backends/Hyperlinker/Types.hs index d8ae89e4..e377471e 100644 --- a/haddock-api/src/Haddock/Backends/Hyperlinker/Types.hs +++ b/haddock-api/src/Haddock/Backends/Hyperlinker/Types.hs @@ -4,8 +4,6 @@ module Haddock.Backends.Hyperlinker.Types where  import qualified GHC  import Data.Map (Map) -import qualified Data.Map as Map -  data Token = Token      { tkType :: TokenType @@ -14,23 +12,8 @@ data Token = Token      }      deriving (Show) -data Position = Position -    { posRow :: !Int -    , posCol :: !Int -    } -    deriving (Eq, Ord, Show) - -data Span = Span -    { spStart :: !Position -    , spEnd   :: !Position -    } -    deriving (Show) - --- | Tests whether the first span "contains" the other span, meaning --- that it covers at least as much source code. True where spans are equal. -containsSpan :: Span -> Span -> Bool -containsSpan s1 s2 = -  spStart s1 <= spStart s2 && spEnd s1 >= spEnd s2 +type Position = GHC.RealSrcLoc +type Span = GHC.RealSrcSpan  data TokenType      = TkIdentifier @@ -80,15 +63,5 @@ data SrcPath      | SrcLocal  -- | Mapping from modules to cross-package source paths. --- --- This mapping is actually a pair of maps instead of just one map. The reason --- for this is because when hyperlinking modules in import lists we have no --- 'GHC.Module' available. On the other hand, we can't just use map with --- 'GHC.ModuleName' as indices because certain modules may have common name --- but originate in different packages. Hence, we use both /rich/ and /poor/ --- versions, where the /poor/ is just projection of /rich/ one cached in pair --- for better performance. -type SrcMap = (Map GHC.Module SrcPath, Map GHC.ModuleName SrcPath) +type SrcMap = Map GHC.Module SrcPath -mkSrcMap :: Map GHC.Module SrcPath -> SrcMap -mkSrcMap srcs = (srcs, Map.mapKeys GHC.moduleName srcs) diff --git a/haddock-api/src/Haddock/Backends/LaTeX.hs b/haddock-api/src/Haddock/Backends/LaTeX.hs index 597f1f15..3cc4c278 100644 --- a/haddock-api/src/Haddock/Backends/LaTeX.hs +++ b/haddock-api/src/Haddock/Backends/LaTeX.hs @@ -27,7 +27,7 @@ import GHC  import OccName  import Name                 ( nameOccName )  import RdrName              ( rdrNameOcc ) -import FastString           ( unpackFS, unpackLitString, zString ) +import FastString           ( unpackFS )  import Outputable           ( panic)  import qualified Data.Map as Map @@ -539,13 +539,11 @@ ppClassDecl instances doc subdocs      methodTable =        text "\\haddockpremethods{}\\textbf{Methods}" $$ -      vcat  [ ppFunSig doc names (hsSigWcType typ) unicode +      vcat  [ ppFunSig doc [name] (hsSigWcType typ) unicode              | L _ (TypeSig _ lnames typ) <- lsigs -            , let doc = lookupAnySubdoc (head names) subdocs -                  names = map unLoc lnames ] -              -- FIXME: is taking just the first name ok? Is it possible that -              -- there are different subdocs for different names in a single -              -- type signature? +            , name <- map unLoc lnames +            , let doc = lookupAnySubdoc name subdocs +            ]      instancesBit = ppDocInstances unicode instances @@ -563,14 +561,14 @@ ppDocInstances unicode (i : rest)      (is, rest') = spanWith isUndocdInstance rest  isUndocdInstance :: DocInstance a -> Maybe (InstHead a) -isUndocdInstance (i,Nothing,_) = Just i +isUndocdInstance (i,Nothing,_,_) = Just i  isUndocdInstance _ = Nothing  -- | Print a possibly commented instance. The instance header is printed inside  -- an 'argBox'. The comment is printed to the right of the box in normal comment  -- style.  ppDocInstance :: Bool -> DocInstance DocNameI -> LaTeX -ppDocInstance unicode (instHead, doc, _) = +ppDocInstance unicode (instHead, doc, _, _) =    declWithDoc (ppInstDecl unicode instHead) (fmap docToLaTeX $ fmap _doc doc) @@ -1139,7 +1137,8 @@ parLatexMarkup ppId = Markup {    markupAName                = \_ _ -> empty,    markupProperty             = \p _ -> quote $ verb $ text p,    markupExample              = \e _ -> quote $ verb $ text $ unlines $ map exampleToString e, -  markupHeader               = \(Header l h) p -> header l (h p) +  markupHeader               = \(Header l h) p -> header l (h p), +  markupTable                = \(Table h b) p -> table h b p    }    where      header 1 d = text "\\section*" <> braces d @@ -1148,6 +1147,8 @@ parLatexMarkup ppId = Markup {        | l > 0 && l <= 6 = text "\\subsubsection*" <> braces d      header l _ = error $ "impossible header level in LaTeX generation: " ++ show l +    table _ _ _ = text "{TODO: Table}" +      fixString Plain s = latexFilter s      fixString Verb  s = s      fixString Mono  s = latexMonoFilter s diff --git a/haddock-api/src/Haddock/Backends/Xhtml.hs b/haddock-api/src/Haddock/Backends/Xhtml.hs index 464c166b..6da6a2e8 100644 --- a/haddock-api/src/Haddock/Backends/Xhtml.hs +++ b/haddock-api/src/Haddock/Backends/Xhtml.hs @@ -70,6 +70,7 @@ ppHtml :: DynFlags         -> 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         -> QualOption                   -- ^ How to qualify names         -> Bool                         -- ^ Output pretty html (newlines and indenting)         -> Bool                         -- ^ Also write Quickjump index @@ -78,7 +79,7 @@ ppHtml :: DynFlags  ppHtml dflags 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 -        qual debug withQuickjump =  do +        pkg qual debug withQuickjump = do    let      visible_ifaces = filter visible ifaces      visible i = OptHide `notElem` ifaceOptions i @@ -88,7 +89,7 @@ ppHtml dflags doctitle maybe_package ifaces reexported_ifaces odir prologue          themes maybe_mathjax_url maybe_index_url maybe_source_url maybe_wiki_url          (map toInstalledIface visible_ifaces ++ reexported_ifaces)          False -- we don't want to display the packages in a single-package contents -        prologue debug (makeContentsQual qual) +        prologue debug pkg (makeContentsQual qual)    when (isNothing maybe_index_url) $ do      ppHtmlIndex odir doctitle maybe_package @@ -96,12 +97,12 @@ ppHtml dflags doctitle maybe_package ifaces reexported_ifaces odir prologue        (map toInstalledIface visible_ifaces ++ reexported_ifaces) debug      when withQuickjump $ -      ppJsonIndex odir maybe_source_url maybe_wiki_url unicode qual +      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 qual debug) visible_ifaces +           maybe_contents_url maybe_index_url unicode pkg qual debug) visible_ifaces  copyHtmlBits :: FilePath -> FilePath -> Themes -> Bool -> IO () @@ -258,11 +259,12 @@ ppHtmlContents     -> WikiURLs     -> [InstalledInterface] -> Bool -> Maybe (MDoc GHC.RdrName)     -> Bool +   -> Maybe Package  -- ^ Current package     -> Qualification  -- ^ How to qualify names     -> IO ()  ppHtmlContents dflags odir doctitle _maybe_package    themes mathjax_url maybe_index_url -  maybe_source_url maybe_wiki_url ifaces showPkgs prologue debug qual = do +  maybe_source_url maybe_wiki_url ifaces showPkgs prologue debug pkg qual = do    let tree = mkModuleTree dflags showPkgs           [(instMod iface, toInstalledDescription iface)           | iface <- ifaces @@ -276,41 +278,41 @@ ppHtmlContents dflags odir doctitle _maybe_package          bodyHtml doctitle Nothing            maybe_source_url maybe_wiki_url            Nothing maybe_index_url << [ -            ppPrologue qual doctitle prologue, -            ppSignatureTree qual sig_tree, -            ppModuleTree qual tree +            ppPrologue pkg qual doctitle prologue, +            ppSignatureTree pkg qual sig_tree, +            ppModuleTree pkg qual tree            ]    createDirectoryIfMissing True odir    writeFile (joinPath [odir, contentsHtmlFile]) (renderToString debug html) -ppPrologue :: Qualification -> String -> Maybe (MDoc GHC.RdrName) -> Html -ppPrologue _ _ Nothing = noHtml -ppPrologue qual title (Just doc) = -  divDescription << (h1 << title +++ docElement thediv (rdrDocToHtml qual doc)) +ppPrologue :: Maybe Package -> Qualification -> String -> Maybe (MDoc GHC.RdrName) -> Html +ppPrologue _ _ _ Nothing = noHtml +ppPrologue pkg qual title (Just doc) = +  divDescription << (h1 << title +++ docElement thediv (rdrDocToHtml pkg qual doc)) -ppSignatureTree :: Qualification -> [ModuleTree] -> Html -ppSignatureTree qual ts = -  divModuleList << (sectionName << "Signatures" +++ mkNodeList qual [] "n" ts) +ppSignatureTree :: Maybe Package -> Qualification -> [ModuleTree] -> Html +ppSignatureTree pkg qual ts = +  divModuleList << (sectionName << "Signatures" +++ mkNodeList pkg qual [] "n" ts) -ppModuleTree :: Qualification -> [ModuleTree] -> Html -ppModuleTree _ [] = mempty -ppModuleTree qual ts = -  divModuleList << (sectionName << "Modules" +++ mkNodeList qual [] "n" ts) +ppModuleTree :: Maybe Package -> Qualification -> [ModuleTree] -> Html +ppModuleTree _ _ [] = mempty +ppModuleTree pkg qual ts = +  divModuleList << (sectionName << "Modules" +++ mkNodeList pkg qual [] "n" ts) -mkNodeList :: Qualification -> [String] -> String -> [ModuleTree] -> Html -mkNodeList qual ss p ts = case ts of +mkNodeList :: Maybe Package -> Qualification -> [String] -> String -> [ModuleTree] -> Html +mkNodeList pkg qual ss p ts = case ts of    [] -> noHtml -  _ -> unordList (zipWith (mkNode qual ss) ps ts) +  _ -> unordList (zipWith (mkNode pkg qual ss) ps ts)    where      ps = [ p ++ '.' : show i | i <- [(1::Int)..]] -mkNode :: Qualification -> [String] -> String -> ModuleTree -> Html -mkNode qual ss p (Node s leaf _pkg srcPkg short ts) = +mkNode :: Maybe Package -> Qualification -> [String] -> String -> ModuleTree -> Html +mkNode pkg qual ss p (Node s leaf _pkg srcPkg short ts) =    htmlModule <+> shortDescr +++ htmlPkg +++ subtree    where      modAttrs = case (ts, leaf) of @@ -330,14 +332,14 @@ mkNode qual ss p (Node s leaf _pkg srcPkg short ts) =          Nothing -> toHtml s        ) -    shortDescr = maybe noHtml (origDocToHtml qual) short +    shortDescr = maybe noHtml (origDocToHtml pkg qual) short      htmlPkg = maybe noHtml (thespan ! [theclass "package"] <<) srcPkg      subtree =        if null ts then noHtml else        collapseDetails p DetailsOpen (          thesummary ! [ theclass "hide-when-js-enabled" ] << "Submodules" +++ -        mkNodeList qual (s:ss) p ts +        mkNodeList pkg qual (s:ss) p ts        ) @@ -350,10 +352,11 @@ ppJsonIndex :: FilePath             -> SourceURLs                   -- ^ The source URL (--source)             -> WikiURLs                     -- ^ The wiki URL (--wiki)             -> Bool +           -> Maybe Package             -> QualOption             -> [Interface]             -> IO () -ppJsonIndex odir maybe_source_url maybe_wiki_url unicode qual_opt ifaces = do +ppJsonIndex odir maybe_source_url maybe_wiki_url unicode pkg qual_opt ifaces = do    createDirectoryIfMissing True odir    IO.withBinaryFile (joinPath [odir, indexJsonFile]) IO.WriteMode $ \h -> do      Builder.hPutBuilder h (encodeToBuilder modules) @@ -371,7 +374,7 @@ ppJsonIndex odir maybe_source_url maybe_wiki_url unicode qual_opt ifaces = do      goExport :: Module -> Qualification -> ExportItem DocNameI -> [Value]      goExport mdl qual item -      | Just item_html <- processExport True links_info unicode qual item +      | Just item_html <- processExport True links_info unicode pkg qual item        = [ Object              [ "display_html" .= String (showHtmlFragment item_html)              , "name"         .= String (intercalate " " (map nameString names)) @@ -529,11 +532,11 @@ ppHtmlIndex odir doctitle _maybe_package themes  ppHtmlModule          :: FilePath -> String -> Themes          -> Maybe String -> SourceURLs -> WikiURLs -        -> Maybe String -> Maybe String -> Bool -> QualOption +        -> Maybe String -> Maybe String -> 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 qual debug iface = do +  maybe_contents_url maybe_index_url unicode pkg qual debug iface = do    let        mdl = ifaceMod iface        aliases = ifaceModuleAliases iface @@ -555,7 +558,7 @@ ppHtmlModule odir doctitle themes            maybe_source_url maybe_wiki_url            maybe_contents_url maybe_index_url << [              divModuleHeader << (moduleInfo iface +++ (sectionName << mdl_str_linked)), -            ifaceToHtml maybe_source_url maybe_wiki_url iface unicode real_qual +            ifaceToHtml maybe_source_url maybe_wiki_url iface unicode pkg real_qual            ]    createDirectoryIfMissing True odir @@ -565,9 +568,9 @@ signatureDocURL :: String  signatureDocURL = "https://wiki.haskell.org/Module_signature" -ifaceToHtml :: SourceURLs -> WikiURLs -> Interface -> Bool -> Qualification -> Html -ifaceToHtml maybe_source_url maybe_wiki_url iface unicode qual -  = ppModuleContents qual exports (not . null $ ifaceRnOrphanInstances iface) +++ +ifaceToHtml :: SourceURLs -> WikiURLs -> Interface -> Bool -> Maybe Package -> Qualification -> Html +ifaceToHtml maybe_source_url maybe_wiki_url iface unicode pkg qual +  = ppModuleContents pkg qual exports (not . null $ ifaceRnOrphanInstances iface) +++      description +++      synopsis +++      divInterface (maybe_doc_hdr +++ bdy +++ orphans) @@ -585,7 +588,7 @@ ifaceToHtml maybe_source_url maybe_wiki_url iface unicode qual      description | isNoHtml doc = doc                  | otherwise    = divDescription $ sectionName << "Description" +++ doc -                where doc = docSection Nothing qual (ifaceRnDoc iface) +                where doc = docSection Nothing pkg qual (ifaceRnDoc iface)          -- omit the synopsis if there are no documentation annotations at all      synopsis @@ -595,7 +598,7 @@ ifaceToHtml maybe_source_url maybe_wiki_url iface unicode qual              collapseDetails "syn" DetailsClosed (                thesummary << "Synopsis" +++                shortDeclList ( -                  mapMaybe (processExport True linksInfo unicode qual) exports +                  mapMaybe (processExport True linksInfo unicode pkg qual) exports                ) ! collapseToggle "syn" ""              ) @@ -609,19 +612,20 @@ ifaceToHtml maybe_source_url maybe_wiki_url iface unicode qual      bdy =        foldr (+++) noHtml $ -        mapMaybe (processExport False linksInfo unicode qual) exports +        mapMaybe (processExport False linksInfo unicode pkg qual) exports      orphans = -      ppOrphanInstances linksInfo (ifaceRnOrphanInstances iface) False unicode qual +      ppOrphanInstances linksInfo (ifaceRnOrphanInstances iface) False unicode pkg qual      linksInfo = (maybe_source_url, maybe_wiki_url) -ppModuleContents :: Qualification +ppModuleContents :: Maybe Package -- ^ This package +                 -> Qualification                   -> [ExportItem DocNameI] -                 -> Bool -- ^ Orphans sections +                 -> Bool          -- ^ Orphans sections                   -> Html -ppModuleContents qual exports orphan +ppModuleContents pkg qual exports orphan    | null sections && not orphan  = noHtml    | otherwise                    = contentsDiv   where @@ -641,7 +645,7 @@ ppModuleContents qual exports orphan      | otherwise = ( html:secs, rest2 )      where        html = linkedAnchor (groupId id0) -             << docToHtmlNoAnchors (Just id0) qual (mkMeta doc) +++ mk_subsections ssecs +             << docToHtmlNoAnchors (Just id0) pkg qual (mkMeta doc) +++ mk_subsections ssecs        (ssecs, rest1) = process lev rest        (secs,  rest2) = process n   rest1    process n (_ : rest) = process n rest @@ -661,22 +665,22 @@ numberSectionHeadings = go 1            = other : go n es -processExport :: Bool -> LinksInfo -> Bool -> Qualification +processExport :: Bool -> LinksInfo -> Bool -> Maybe Package -> Qualification                -> ExportItem DocNameI -> Maybe Html -processExport _ _ _ _ ExportDecl { expItemDecl = L _ (InstD {}) } = Nothing -- Hide empty instances -processExport summary _ _ qual (ExportGroup lev id0 doc) -  = nothingIf summary $ groupHeading lev id0 << docToHtml (Just id0) qual (mkMeta doc) -processExport summary links unicode qual (ExportDecl decl pats doc subdocs insts fixities splice) -  = processDecl summary $ ppDecl summary links decl pats doc insts fixities subdocs splice unicode qual -processExport summary _ _ qual (ExportNoDecl y []) +processExport _ _ _ _ _ ExportDecl { expItemDecl = L _ (InstD {}) } = Nothing -- Hide empty instances +processExport summary _ _ pkg qual (ExportGroup lev id0 doc) +  = nothingIf summary $ groupHeading lev id0 << docToHtml (Just id0) pkg qual (mkMeta doc) +processExport summary links unicode pkg qual (ExportDecl decl pats doc subdocs insts fixities splice) +  = processDecl summary $ ppDecl summary links decl pats doc insts fixities subdocs splice unicode pkg qual +processExport summary _ _ _ qual (ExportNoDecl y [])    = processDeclOneLiner summary $ ppDocName qual Prefix True y -processExport summary _ _ qual (ExportNoDecl y subs) +processExport summary _ _ _ qual (ExportNoDecl y subs)    = processDeclOneLiner summary $        ppDocName qual Prefix True y        +++ parenList (map (ppDocName qual Prefix True) subs) -processExport summary _ _ qual (ExportDoc doc) -  = nothingIf summary $ docSection_ Nothing qual doc -processExport summary _ _ _ (ExportModule mdl) +processExport summary _ _ pkg qual (ExportDoc doc) +  = nothingIf summary $ docSection_ Nothing pkg qual doc +processExport summary _ _ _ _ (ExportModule mdl)    = processDeclOneLiner summary $ toHtml "module" <+> ppModule mdl @@ -698,7 +702,8 @@ processDeclOneLiner True = Just  processDeclOneLiner False = Just . divTopDecl . declElem  groupHeading :: Int -> String -> Html -> Html -groupHeading lev id0 = groupTag lev ! [identifier (groupId id0)] +groupHeading lev id0 = linkedAnchor grpId . groupTag lev ! [identifier grpId] +  where grpId = groupId id0  groupTag :: Int -> Html -> Html  groupTag lev diff --git a/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs b/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs index fe33fbe9..819c9aa6 100644 --- a/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs +++ b/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs @@ -52,36 +52,37 @@ ppDecl :: Bool                                     -- ^ print summary info only         -> [(DocName, DocForDecl DocName)]          -- ^ documentation for all decls         -> Splice         -> Unicode                                  -- ^ unicode output +       -> Maybe Package         -> Qualification         -> Html -ppDecl summ links (L loc decl) pats (mbDoc, fnArgsDoc) instances fixities subdocs splice unicode qual = case decl of -  TyClD _ (FamDecl _ d)          -> ppTyFam summ False links instances fixities loc mbDoc d splice unicode qual -  TyClD _ d@(DataDecl {})        -> ppDataDecl summ links instances fixities subdocs loc mbDoc d pats splice unicode qual -  TyClD _ d@(SynDecl {})         -> ppTySyn summ links fixities loc (mbDoc, fnArgsDoc) d splice unicode qual -  TyClD _ d@(ClassDecl {})       -> ppClassDecl summ links instances fixities loc mbDoc subdocs d splice unicode qual +ppDecl summ links (L loc decl) pats (mbDoc, fnArgsDoc) instances fixities subdocs splice unicode pkg qual = case decl of +  TyClD _ (FamDecl _ d)          -> ppTyFam summ False links instances fixities loc mbDoc d splice unicode pkg qual +  TyClD _ d@(DataDecl {})        -> ppDataDecl summ links instances fixities subdocs loc mbDoc d pats splice unicode pkg qual +  TyClD _ d@(SynDecl {})         -> ppTySyn summ links fixities loc (mbDoc, fnArgsDoc) d splice unicode pkg qual +  TyClD _ d@(ClassDecl {})       -> ppClassDecl summ links instances fixities loc mbDoc subdocs d splice unicode pkg qual    SigD _ (TypeSig _ lnames lty)  -> ppLFunSig summ links loc (mbDoc, fnArgsDoc) lnames -                                         (hsSigWcType lty) fixities splice unicode qual +                                         (hsSigWcType lty) fixities splice unicode pkg qual    SigD _ (PatSynSig _ lnames lty) -> ppLPatSig summ links loc (mbDoc, fnArgsDoc) lnames -                                         (hsSigType lty) fixities splice unicode qual -  ForD _ d                       -> ppFor summ links loc (mbDoc, fnArgsDoc) d fixities splice unicode qual +                                         (hsSigType lty) fixities splice unicode pkg qual +  ForD _ d                       -> ppFor summ links loc (mbDoc, fnArgsDoc) d fixities splice unicode pkg qual    InstD _ _                      -> noHtml    DerivD _ _                     -> noHtml -  _                              -> error "declaration not supported by ppDecl" +  _                            -> error "declaration not supported by ppDecl"  ppLFunSig :: Bool -> LinksInfo -> SrcSpan -> DocForDecl DocName ->               [Located DocName] -> LHsType DocNameI -> [(DocName, Fixity)] -> -             Splice -> Unicode -> Qualification -> Html -ppLFunSig summary links loc doc lnames lty fixities splice unicode qual = +             Splice -> Unicode -> Maybe Package -> Qualification -> Html +ppLFunSig summary links loc doc lnames lty fixities splice unicode pkg qual =    ppFunSig summary links loc doc (map unLoc lnames) lty fixities -           splice unicode qual +           splice unicode pkg qual  ppFunSig :: Bool -> LinksInfo -> SrcSpan -> DocForDecl DocName ->              [DocName] -> LHsType DocNameI -> [(DocName, Fixity)] -> -            Splice -> Unicode -> Qualification -> Html -ppFunSig summary links loc doc docnames typ fixities splice unicode qual = +            Splice -> Unicode -> Maybe Package -> Qualification -> Html +ppFunSig summary links loc doc docnames typ fixities splice unicode pkg qual =    ppSigLike summary links loc mempty doc docnames fixities (unLoc typ, pp_typ) -            splice unicode qual HideEmptyContexts +            splice unicode pkg qual HideEmptyContexts    where      pp_typ = ppLType unicode qual HideEmptyContexts typ @@ -90,25 +91,25 @@ ppLPatSig :: Bool -> LinksInfo -> SrcSpan -> DocForDecl DocName            -> [Located DocName]     -- ^ names of patterns in declaration            -> LHsType DocNameI      -- ^ type of patterns in declaration            -> [(DocName, Fixity)] -          -> Splice -> Unicode -> Qualification -> Html -ppLPatSig summary links loc doc lnames typ fixities splice unicode qual = +          -> Splice -> Unicode -> Maybe Package -> Qualification -> Html +ppLPatSig summary links loc doc lnames typ fixities splice unicode pkg qual =    ppSigLike summary links loc (keyword "pattern") doc (map unLoc lnames) fixities -            (unLoc typ, pp_typ) splice unicode qual (patSigContext typ) +            (unLoc typ, pp_typ) splice unicode pkg qual (patSigContext typ)    where      pp_typ = ppPatSigType unicode qual typ  ppSigLike :: Bool -> LinksInfo -> SrcSpan -> Html -> DocForDecl DocName ->               [DocName] -> [(DocName, Fixity)] -> (HsType DocNameI, Html) -> -             Splice -> Unicode -> Qualification -> HideEmptyContexts -> Html +             Splice -> Unicode -> Maybe Package -> Qualification -> HideEmptyContexts -> Html  ppSigLike summary links loc leader doc docnames fixities (typ, pp_typ) -          splice unicode qual emptyCtxts = +          splice unicode pkg qual emptyCtxts =    ppTypeOrFunSig summary links loc docnames typ doc      ( addFixities $ leader <+> ppTypeSig summary occnames pp_typ unicode      , (leader <+>) . addFixities . concatHtml . punctuate comma $ map (ppBinder False) occnames      , dcolon unicode      ) -    splice unicode qual emptyCtxts +    splice unicode pkg qual emptyCtxts    where      occnames = map (nameOccName . getName) docnames      addFixities html @@ -118,13 +119,15 @@ ppSigLike summary links loc leader doc docnames fixities (typ, pp_typ)  ppTypeOrFunSig :: Bool -> LinksInfo -> SrcSpan -> [DocName] -> HsType DocNameI                 -> DocForDecl DocName -> (Html, Html, Html) -               -> Splice -> Unicode -> Qualification -> HideEmptyContexts -> Html -ppTypeOrFunSig summary links loc docnames typ (doc, argDocs) (pref1, pref2, sep) splice unicode qual emptyCtxts +               -> Splice -> Unicode -> Maybe Package -> Qualification +               -> HideEmptyContexts -> Html +ppTypeOrFunSig summary links loc docnames typ (doc, argDocs) (pref1, pref2, sep) +               splice unicode pkg qual emptyCtxts    | summary = pref1 -  | Map.null argDocs = topDeclElem links loc splice docnames pref1 +++ docSection curName qual doc +  | Map.null argDocs = topDeclElem links loc splice docnames pref1 +++ docSection curName pkg qual doc    | otherwise = topDeclElem links loc splice docnames pref2 -                  +++ subArguments qual (ppSubSigLike unicode qual typ argDocs [] sep emptyCtxts) -                  +++ docSection curName qual doc +                  +++ subArguments pkg qual (ppSubSigLike unicode qual typ argDocs [] sep emptyCtxts) +                  +++ docSection curName pkg qual doc    where      curName = getName <$> listToMaybe docnames @@ -225,23 +228,23 @@ tyvarNames = map (getName . hsLTyVarName) . hsQTvExplicit  ppFor :: Bool -> LinksInfo -> SrcSpan -> DocForDecl DocName        -> ForeignDecl DocNameI -> [(DocName, Fixity)] -      -> Splice -> Unicode -> Qualification -> Html +      -> Splice -> Unicode -> Maybe Package -> Qualification -> Html  ppFor summary links loc doc (ForeignImport _ (L _ name) typ _) fixities -      splice unicode qual -  = ppFunSig summary links loc doc [name] (hsSigType typ) fixities splice unicode qual -ppFor _ _ _ _ _ _ _ _ _ = error "ppFor" +      splice unicode pkg qual +  = ppFunSig summary links loc doc [name] (hsSigType typ) fixities splice unicode pkg qual +ppFor _ _ _ _ _ _ _ _ _ _ = error "ppFor"  -- we skip type patterns for now  ppTySyn :: Bool -> LinksInfo -> [(DocName, Fixity)] -> SrcSpan          -> DocForDecl DocName -> TyClDecl DocNameI -        -> Splice -> Unicode -> Qualification -> Html +        -> Splice -> Unicode -> Maybe Package -> Qualification -> Html  ppTySyn summary links fixities loc doc (SynDecl { tcdLName = L _ name, tcdTyVars = ltyvars                                                  , tcdRhs = ltype }) -        splice unicode qual +        splice unicode pkg qual    = ppTypeOrFunSig summary links loc [name] (unLoc ltype) doc                     (full <+> fixs, hdr <+> fixs, spaceHtml +++ equals) -                   splice unicode qual ShowEmptyToplevelContexts +                   splice unicode pkg qual ShowEmptyToplevelContexts    where      hdr  = hsep ([keyword "type", ppBinder summary occ]                   ++ ppTyVars unicode qual (hsQTvExplicit ltyvars)) @@ -250,7 +253,7 @@ ppTySyn summary links fixities loc doc (SynDecl { tcdLName = L _ name, tcdTyVars      fixs        | summary   = noHtml        | otherwise = ppFixities fixities qual -ppTySyn _ _ _ _ _ _ _ _ _ = error "declaration not supported by ppTySyn" +ppTySyn _ _ _ _ _ _ _ _ _ _ = error "declaration not supported by ppTySyn"  ppTypeSig :: Bool -> [OccName] -> Html -> Unicode -> Html @@ -343,11 +346,13 @@ ppInjectivityAnn unicode qual (InjectivityAnn lhs rhs) =  ppTyFam :: Bool -> Bool -> LinksInfo -> [DocInstance DocNameI] ->             [(DocName, Fixity)] -> SrcSpan -> Documentation DocName -> -           FamilyDecl DocNameI -> Splice -> Unicode -> Qualification -> Html -ppTyFam summary associated links instances fixities loc doc decl splice unicode qual +           FamilyDecl DocNameI -> Splice -> Unicode -> Maybe Package -> +           Qualification -> Html +ppTyFam summary associated links instances fixities loc doc decl splice unicode +        pkg qual    | summary   = ppTyFamHeader True associated decl unicode qual -  | otherwise = header_ +++ docSection Nothing qual doc +++ instancesBit +  | otherwise = header_ +++ docSection Nothing pkg qual doc +++ instancesBit    where      docname = unLoc $ fdLName decl @@ -358,10 +363,10 @@ ppTyFam summary associated links instances fixities loc doc decl splice unicode      instancesBit        | FamilyDecl { fdInfo = ClosedTypeFamily mb_eqns } <- decl        , not summary -      = subEquations qual $ map (ppTyFamEqn . unLoc) $ fromMaybe [] mb_eqns +      = subEquations pkg qual $ map (ppTyFamEqn . unLoc) $ fromMaybe [] mb_eqns        | otherwise -      = ppInstances links (OriginFamily docname) instances splice unicode qual +      = ppInstances links (OriginFamily docname) instances splice unicode pkg qual      -- Individual equation of a closed type family      ppTyFamEqn :: TyFamInstEqn DocNameI -> SubDecl @@ -391,9 +396,10 @@ ppPseudoFamilyDecl links splice unicode qual  ppAssocType :: Bool -> LinksInfo -> DocForDecl DocName -> LFamilyDecl DocNameI -            -> [(DocName, Fixity)] -> Splice -> Unicode -> Qualification -> Html -ppAssocType summ links doc (L loc decl) fixities splice unicode qual = -   ppTyFam summ True links [] fixities loc (fst doc) decl splice unicode qual +            -> [(DocName, Fixity)] -> Splice -> Unicode -> Maybe Package +            -> Qualification -> Html +ppAssocType summ links doc (L loc decl) fixities splice unicode pkg qual = +   ppTyFam summ True links [] fixities loc (fst doc) decl splice unicode pkg qual  -------------------------------------------------------------------------------- @@ -503,23 +509,23 @@ ppFds fds unicode qual =  ppShortClassDecl :: Bool -> LinksInfo -> TyClDecl DocNameI -> SrcSpan                   -> [(DocName, DocForDecl DocName)] -                 -> Splice -> Unicode -> Qualification -> Html +                 -> Splice -> Unicode -> Maybe Package -> Qualification -> Html  ppShortClassDecl summary links (ClassDecl { tcdCtxt = lctxt, tcdLName = lname, tcdTyVars = tvs                                            , tcdFDs = fds, tcdSigs = sigs, tcdATs = ats }) loc -    subdocs splice unicode qual = +    subdocs splice unicode pkg qual =    if not (any isUserLSig sigs) && null ats      then (if summary then id else topDeclElem links loc splice [nm]) hdr      else (if summary then id else topDeclElem links loc splice [nm]) (hdr <+> keyword "where")        +++ shortSubDecls False            ( -            [ ppAssocType summary links doc at [] splice unicode qual | at <- ats +            [ ppAssocType summary links doc at [] splice unicode pkg qual | at <- ats                , let doc = lookupAnySubdoc (unL $ fdLName $ unL at) subdocs ]  ++                  -- ToDo: add associated type defaults -            [ ppFunSig summary links loc doc names (hsSigWcType typ) -                       [] splice unicode qual -              | L _ (TypeSig _ lnames typ) <- sigs +            [ ppFunSig summary links loc doc names (hsSigType typ) +                       [] splice unicode pkg qual +              | L _ (ClassOpSig _ False lnames typ) <- sigs                , let doc = lookupAnySubdoc (head names) subdocs                      names = map unLoc lnames ]                -- FIXME: is taking just the first name ok? Is it possible that @@ -529,20 +535,20 @@ ppShortClassDecl summary links (ClassDecl { tcdCtxt = lctxt, tcdLName = lname, t    where      hdr = ppClassHdr summary lctxt (unLoc lname) tvs fds unicode qual      nm  = unLoc lname -ppShortClassDecl _ _ _ _ _ _ _ _ = error "declaration type not supported by ppShortClassDecl" +ppShortClassDecl _ _ _ _ _ _ _ _ _ = error "declaration type not supported by ppShortClassDecl"  ppClassDecl :: Bool -> LinksInfo -> [DocInstance DocNameI] -> [(DocName, Fixity)]              -> SrcSpan -> Documentation DocName              -> [(DocName, DocForDecl DocName)] -> TyClDecl DocNameI -            -> Splice -> Unicode -> Qualification -> Html +            -> Splice -> Unicode -> Maybe Package -> Qualification -> Html  ppClassDecl summary links instances fixities loc d subdocs          decl@(ClassDecl { tcdCtxt = lctxt, tcdLName = lname, tcdTyVars = ltyvars                          , tcdFDs = lfds, tcdSigs = lsigs, tcdATs = ats }) -            splice unicode qual -  | summary = ppShortClassDecl summary links decl loc subdocs splice unicode qual -  | otherwise = classheader +++ docSection Nothing qual d +            splice unicode pkg qual +  | summary = ppShortClassDecl summary links decl loc subdocs splice unicode pkg qual +  | otherwise = classheader +++ docSection Nothing pkg qual d                    +++ minimalBit +++ atBit +++ methodBit +++ instancesBit    where      sigs = map unLoc lsigs @@ -559,32 +565,32 @@ ppClassDecl summary links instances fixities loc d subdocs      hdr = ppClassHdr summary lctxt (unLoc lname) ltyvars lfds      -- ToDo: add assocatied typ defaults -    atBit = subAssociatedTypes [ ppAssocType summary links doc at subfixs splice unicode qual +    atBit = subAssociatedTypes [ ppAssocType summary links doc at subfixs splice unicode pkg qual                        | at <- ats                        , let n = unL . fdLName $ unL at                              doc = lookupAnySubdoc (unL $ fdLName $ unL at) subdocs                              subfixs = [ f | f@(n',_) <- fixities, n == n' ] ] -    methodBit = subMethods [ ppFunSig summary links loc doc names (hsSigType typ) -                                      subfixs splice unicode qual +    methodBit = subMethods [ ppFunSig summary links loc doc [name] (hsSigType typ) +                                      subfixs splice unicode pkg qual                             | L _ (ClassOpSig _ _ lnames typ) <- lsigs -                           , let doc = lookupAnySubdoc (head names) subdocs -                                 subfixs = [ f | n <- names -                                               , f@(n',_) <- fixities -                                               , n == n' ] -                                 names = map unLoc lnames ] +                           , name <- map unLoc lnames +                           , let doc = lookupAnySubdoc name subdocs +                                 subfixs = [ f | f@(n',_) <- fixities +                                               , name == n' ] +                           ]                             -- N.B. taking just the first name is ok. Signatures with multiple names                             -- are expanded so that each name gets its own signature.      minimalBit = case [ s | MinimalSig _ _ (L _ s) <- sigs ] of        -- Miminal complete definition = every shown method        And xs : _ | sort [getName n | L _ (Var (L _ n)) <- xs] == -                   sort [getName n | TypeSig _ ns _ <- sigs, L _ n <- ns] +                   sort [getName n | ClassOpSig _ _ ns _ <- sigs, L _ n <- ns]          -> noHtml        -- Minimal complete definition = the only shown method        Var (L _ n) : _ | [getName n] == -                        [getName n' | L _ (TypeSig _ ns _) <- lsigs, L _ n' <- ns] +                        [getName n' | L _ (ClassOpSig _ _ ns _) <- lsigs, L _ n' <- ns]          -> noHtml        -- Minimal complete definition = nothing @@ -600,38 +606,38 @@ ppClassDecl summary links instances fixities loc d subdocs      ppMinimal p (Parens x) = ppMinimal p (unLoc x)      instancesBit = ppInstances links (OriginClass nm) instances -        splice unicode qual +        splice unicode pkg qual -ppClassDecl _ _ _ _ _ _ _ _ _ _ _ = error "declaration type not supported by ppShortClassDecl" +ppClassDecl _ _ _ _ _ _ _ _ _ _ _ _ = error "declaration type not supported by ppShortClassDecl"  ppInstances :: LinksInfo              -> InstOrigin DocName -> [DocInstance DocNameI] -            -> Splice -> Unicode -> Qualification +            -> Splice -> Unicode -> Maybe Package -> Qualification              -> Html -ppInstances links origin instances splice unicode qual -  = subInstances qual instName links True (zipWith instDecl [1..] instances) +ppInstances links origin instances splice unicode pkg qual +  = subInstances pkg qual instName links True (zipWith instDecl [1..] instances)    -- force Splice = True to use line URLs    where      instName = getOccString origin      instDecl :: Int -> DocInstance DocNameI -> (SubDecl,Located DocName) -    instDecl no (inst, mdoc, loc) = -        ((ppInstHead links splice unicode qual mdoc origin False no inst), loc) +    instDecl no (inst, mdoc, loc, mdl) = +        ((ppInstHead links splice unicode qual mdoc origin False no inst mdl), loc)  ppOrphanInstances :: LinksInfo                    -> [DocInstance DocNameI] -                  -> Splice -> Unicode -> Qualification +                  -> Splice -> Unicode -> Maybe Package -> Qualification                    -> Html -ppOrphanInstances links instances splice unicode qual -  = subOrphanInstances qual links True (zipWith instDecl [1..] instances) +ppOrphanInstances links instances splice unicode pkg qual +  = subOrphanInstances pkg qual links True (zipWith instDecl [1..] instances)    where      instOrigin :: InstHead name -> InstOrigin (IdP name)      instOrigin inst = OriginClass (ihdClsName inst)      instDecl :: Int -> DocInstance DocNameI -> (SubDecl,Located DocName) -    instDecl no (inst, mdoc, loc) = -        ((ppInstHead links splice unicode qual mdoc (instOrigin inst) True no inst), loc) +    instDecl no (inst, mdoc, loc, mdl) = +        ((ppInstHead links splice unicode qual mdoc (instOrigin inst) True no inst mdl), loc)  ppInstHead :: LinksInfo -> Splice -> Unicode -> Qualification @@ -640,13 +646,14 @@ ppInstHead :: LinksInfo -> Splice -> Unicode -> Qualification             -> Bool -- ^ Is instance orphan             -> Int  -- ^ Normal             -> InstHead DocNameI +           -> Maybe Module             -> SubDecl -ppInstHead links splice unicode qual mdoc origin orphan no ihd@(InstHead {..}) = +ppInstHead links splice unicode qual mdoc origin orphan no ihd@(InstHead {..}) mdl =      case ihdInstType of          ClassInst { .. } ->              ( subInstHead iid $ ppContextNoLocs clsiCtx unicode qual HideEmptyContexts <+> typ              , mdoc -            , [subInstDetails iid ats sigs] +            , [subInstDetails iid ats sigs mname]              )            where              sigs = ppInstanceSigs links splice unicode qual clsiSigs @@ -654,7 +661,7 @@ ppInstHead links splice unicode qual mdoc origin orphan no ihd@(InstHead {..}) =          TypeInst rhs ->              ( subInstHead iid ptype              , mdoc -            , [subFamInstDetails iid prhs] +            , [subFamInstDetails iid prhs mname]              )            where              ptype = keyword "type" <+> typ @@ -663,11 +670,12 @@ ppInstHead links splice unicode qual mdoc origin orphan no ihd@(InstHead {..}) =          DataInst dd ->              ( subInstHead iid pdata              , mdoc -            , [subFamInstDetails iid pdecl]) +            , [subFamInstDetails iid pdecl mname])            where              pdata = keyword "data" <+> typ              pdecl = pdata <+> ppShortDataDecl False True dd [] unicode qual    where +    mname = maybe noHtml (\m -> toHtml "Defined in" <+> ppModule m) mdl      iid = instanceId origin no orphan ihd      typ = ppAppNameTypes ihdClsName ihdTypes unicode qual @@ -766,12 +774,12 @@ ppDataDecl :: Bool -> LinksInfo             -> Documentation DocName                   -- ^ this decl's documentation             -> TyClDecl DocNameI                       -- ^ this decl             -> [(HsDecl DocNameI, DocForDecl DocName)] -- ^ relevant patterns -           -> Splice -> Unicode -> Qualification -> Html +           -> Splice -> Unicode -> Maybe Package -> Qualification -> Html  ppDataDecl summary links instances fixities subdocs loc doc dataDecl pats -           splice unicode qual +           splice unicode pkg qual    | summary   = ppShortDataDecl summary False dataDecl pats unicode qual -  | otherwise = header_ +++ docSection Nothing qual doc +++ constrBit +++ patternBit +++ instancesBit +  | otherwise = header_ +++ docSection Nothing pkg qual doc +++ constrBit +++ patternBit +++ instancesBit    where      docname   = tcdName dataDecl @@ -792,14 +800,14 @@ ppDataDecl summary links instances fixities subdocs loc doc dataDecl pats        | null cons = keyword "where"        | otherwise = if isH98 then noHtml else keyword "where" -    constrBit = subConstructors qual -      [ ppSideBySideConstr subdocs subfixs unicode qual c +    constrBit = subConstructors pkg qual +      [ ppSideBySideConstr subdocs subfixs unicode pkg qual c        | c <- cons        , let subfixs = filter (\(n,_) -> any (\cn -> cn == n)                                              (map unLoc (getConNames (unLoc c)))) fixities        ] -    patternBit = subPatterns qual +    patternBit = subPatterns pkg qual        [ ppSideBySidePat subfixs unicode qual lnames typ d        | (SigD _ (PatSynSig _ lnames typ), d) <- pats        , let subfixs = filter (\(n,_) -> any (\cn -> cn == n) @@ -807,7 +815,7 @@ ppDataDecl summary links instances fixities subdocs loc doc dataDecl pats        ]      instancesBit = ppInstances links (OriginData docname) instances -        splice unicode qual +        splice unicode pkg qual  ppShortConstr :: Bool -> ConDecl DocNameI -> Unicode -> Qualification -> Html @@ -872,10 +880,10 @@ ppShortConstrParts summary dataInst con unicode qual  -- | Pretty print an expanded constructor  ppSideBySideConstr :: [(DocName, DocForDecl DocName)] -> [(DocName, Fixity)] -                   -> Unicode -> Qualification +                   -> Unicode -> Maybe Package -> Qualification                     -> LConDecl DocNameI -- ^ constructor declaration to print                     -> SubDecl -ppSideBySideConstr subdocs fixities unicode qual (L _ con) +ppSideBySideConstr subdocs fixities unicode pkg qual (L _ con)   = ( decl       -- Constructor header (name, fixity)     , mbDoc      -- Docs on the whole constructor     , fieldPart  -- Information on the fields (or arguments, if they have docs) @@ -949,10 +957,10 @@ ppSideBySideConstr subdocs fixities unicode qual (L _ con)          _ -> [] -    doRecordFields fields = subFields qual +    doRecordFields fields = subFields pkg qual        (map (ppSideBySideField subdocs unicode qual) (map unLoc fields)) -    doConstrArgsWithDocs args = subFields qual $ case con of +    doConstrArgsWithDocs args = subFields pkg qual $ case con of        ConDeclH98{} ->          [ (ppLParendType unicode qual HideEmptyContexts arg, mdoc, [])          | (i, arg) <- zip [0..] args @@ -1041,7 +1049,7 @@ ppSideBySidePat fixities unicode qual lnames typ (doc, argDocs) =      fieldPart        | not hasArgDocs = [] -      | otherwise = [ subFields qual (ppSubSigLike unicode qual (unLoc patTy) +      | otherwise = [ subFields Nothing qual (ppSubSigLike unicode qual (unLoc patTy)                                                          argDocs [] (dcolon unicode)                                                          emptyCtxt) ] diff --git a/haddock-api/src/Haddock/Backends/Xhtml/DocMarkup.hs b/haddock-api/src/Haddock/Backends/Xhtml/DocMarkup.hs index e63667b0..ed323a90 100644 --- a/haddock-api/src/Haddock/Backends/Xhtml/DocMarkup.hs +++ b/haddock-api/src/Haddock/Backends/Xhtml/DocMarkup.hs @@ -73,7 +73,8 @@ parHtmlMarkup qual insertAnchors ppId = Markup {    markupMathDisplay          = \mathjax -> toHtml ("\\[" ++ mathjax ++ "\\]"),    markupProperty             = pre . toHtml,    markupExample              = examplesToHtml, -  markupHeader               = \(Header l t) -> makeHeader l t +  markupHeader               = \(Header l t) -> makeHeader l t, +  markupTable                = \(Table h r) -> makeTable h r    }    where      makeHeader :: Int -> Html -> Html @@ -85,6 +86,22 @@ parHtmlMarkup qual insertAnchors ppId = Markup {      makeHeader 6 mkup = h6 mkup      makeHeader l _ = error $ "Somehow got a header level `" ++ show l ++ "' in DocMarkup!" +    makeTable :: [TableRow Html] -> [TableRow Html] -> Html +    makeTable hs bs = table (concatHtml (hs' ++ bs')) +      where +        hs' | null hs   = [] +            | otherwise = [thead (concatHtml (map (makeTableRow th) hs))] + +        bs' = [tbody (concatHtml (map (makeTableRow td) bs))] + +    makeTableRow :: (Html -> Html) -> TableRow Html -> Html +    makeTableRow thr (TableRow cs) = tr (concatHtml (map (makeTableCell thr) cs)) + +    makeTableCell :: (Html -> Html) -> TableCell Html -> Html +    makeTableCell thr (TableCell i j c) = thr c ! (i' ++ j') +      where +        i' = if i == 1 then [] else [ colspan i ] +        j' = if j == 1 then [] else [ rowspan j ]      examplesToHtml l = pre (concatHtml $ map exampleToHtml l) ! [theclass "screen"] @@ -154,10 +171,10 @@ flatten x = [x]  -- extract/append the underlying 'Doc' and convert it to 'Html'. For  -- 'CollapsingHeader', we attach extra info to the generated 'Html'  -- that allows us to expand/collapse the content. -hackMarkup :: DocMarkup id Html -> Hack (ModuleName, OccName) id -> Html -hackMarkup fmt' h' = +hackMarkup :: DocMarkup id Html -> Maybe Package -> Hack (ModuleName, OccName) id -> Html +hackMarkup fmt' currPkg h' =    let (html, ms) = hackMarkup' fmt' h' -  in html +++ renderMeta fmt' (metaConcat ms) +  in html +++ renderMeta fmt' currPkg (metaConcat ms)    where      hackMarkup' :: DocMarkup id Html -> Hack (ModuleName, OccName) id                  -> (Html, [Meta]) @@ -176,45 +193,50 @@ hackMarkup fmt' h' =                               (y, m') = hackMarkup' fmt d'                           in (markupAppend fmt x y, m ++ m') -renderMeta :: DocMarkup id Html -> Meta -> Html -renderMeta fmt (Meta { _version = Just x }) = +renderMeta :: DocMarkup id Html -> Maybe Package -> Meta -> Html +renderMeta fmt currPkg (Meta { _version = Just x, _package = pkg }) =    markupParagraph fmt . markupEmphasis fmt . toHtml $ -    "Since: " ++ formatVersion x +    "Since: " ++ formatPkgMaybe pkg ++ formatVersion x    where      formatVersion v = concat . intersperse "." $ map show v -renderMeta _ _ = noHtml +    formatPkgMaybe (Just p) | Just p /= currPkg = p ++ "-" +    formatPkgMaybe _ = "" +renderMeta _ _ _ = noHtml  -- | Goes through 'hackMarkup' to generate the 'Html' rather than  -- skipping straight to 'markup': this allows us to employ XHtml  -- specific hacks to the tree first.  markupHacked :: DocMarkup id Html +             -> Maybe Package      -- this package               -> Maybe String               -> MDoc id               -> Html -markupHacked fmt n = hackMarkup fmt . toHack 0 n . flatten +markupHacked fmt currPkg n = hackMarkup fmt currPkg . toHack 0 n . flatten  -- If the doc is a single paragraph, don't surround it with <P> (this causes  -- ugly extra whitespace with some browsers).  FIXME: Does this still apply? -docToHtml :: Maybe String -- ^ Name of the thing this doc is for. See -                          -- comments on 'toHack' for details. +docToHtml :: Maybe String  -- ^ Name of the thing this doc is for. See +                           -- comments on 'toHack' for details. +          -> Maybe Package -- ^ Current package            -> Qualification -> MDoc DocName -> Html -docToHtml n qual = markupHacked fmt n . cleanup +docToHtml n pkg qual = markupHacked fmt pkg n . cleanup    where fmt = parHtmlMarkup qual True (ppDocName qual Raw)  -- | Same as 'docToHtml' but it doesn't insert the 'anchor' element  -- in links. This is used to generate the Contents box elements. -docToHtmlNoAnchors :: Maybe String -- ^ See 'toHack' +docToHtmlNoAnchors :: Maybe String  -- ^ See 'toHack' +                   -> Maybe Package -- ^ Current package                     -> Qualification -> MDoc DocName -> Html -docToHtmlNoAnchors n qual = markupHacked fmt n . cleanup +docToHtmlNoAnchors n pkg qual = markupHacked fmt pkg n . cleanup    where fmt = parHtmlMarkup qual False (ppDocName qual Raw) -origDocToHtml :: Qualification -> MDoc Name -> Html -origDocToHtml qual = markupHacked fmt Nothing . cleanup +origDocToHtml :: Maybe Package -> Qualification -> MDoc Name -> Html +origDocToHtml pkg qual = markupHacked fmt pkg Nothing . cleanup    where fmt = parHtmlMarkup qual True (const $ ppName Raw) -rdrDocToHtml :: Qualification -> MDoc RdrName -> Html -rdrDocToHtml qual = markupHacked fmt Nothing . cleanup +rdrDocToHtml :: Maybe Package -> Qualification -> MDoc RdrName -> Html +rdrDocToHtml pkg qual = markupHacked fmt pkg Nothing . cleanup    where fmt = parHtmlMarkup qual True (const ppRdrName) @@ -226,14 +248,17 @@ docElement el content_ =  docSection :: Maybe Name -- ^ Name of the thing this doc is for +           -> Maybe Package -- ^ Current package             -> Qualification -> Documentation DocName -> Html -docSection n qual = maybe noHtml (docSection_ n qual) . combineDocumentation +docSection n pkg qual = +  maybe noHtml (docSection_ n pkg qual) . combineDocumentation -docSection_ :: Maybe Name -- ^ Name of the thing this doc is for +docSection_ :: Maybe Name    -- ^ Name of the thing this doc is for +            -> Maybe Package -- ^ Current package              -> Qualification -> MDoc DocName -> Html -docSection_ n qual = -  (docElement thediv <<) . docToHtml (getOccString <$> n) qual +docSection_ n pkg qual = +  (docElement thediv <<) . docToHtml (getOccString <$> n) pkg qual  cleanup :: MDoc a -> MDoc a diff --git a/haddock-api/src/Haddock/Backends/Xhtml/Layout.hs b/haddock-api/src/Haddock/Backends/Xhtml/Layout.hs index e020b909..501caa4b 100644 --- a/haddock-api/src/Haddock/Backends/Xhtml/Layout.hs +++ b/haddock-api/src/Haddock/Backends/Xhtml/Layout.hs @@ -47,7 +47,7 @@ import Haddock.Backends.Xhtml.Utils  import Haddock.Types  import Haddock.Utils (makeAnchorId, nameAnchorId)  import qualified Data.Map as Map -import Text.XHtml hiding ( name, title, p, quote ) +import Text.XHtml hiding ( name, title, quote )  import FastString            ( unpackFS )  import GHC @@ -128,38 +128,39 @@ divSubDecls cssClass captionName = maybe noHtml wrap      subCaption = paragraph ! [theclass "caption"] << captionName -subDlist :: Qualification -> [SubDecl] -> Maybe Html -subDlist _ [] = Nothing -subDlist qual decls = Just $ ulist << map subEntry decls +subDlist :: Maybe Package -> Qualification -> [SubDecl] -> Maybe Html +subDlist _ _ [] = Nothing +subDlist pkg qual decls = Just $ ulist << map subEntry decls    where      subEntry (decl, mdoc, subs) =        li <<          (define ! [theclass "src"] << decl +++ -         docElement thediv << (fmap (docToHtml Nothing qual) mdoc +++ subs)) +         docElement thediv << (fmap (docToHtml Nothing pkg qual) mdoc +++ subs)) -subTable :: Qualification -> [SubDecl] -> Maybe Html -subTable _ [] = Nothing -subTable qual decls = Just $ table << aboves (concatMap subRow decls) +subTable :: Maybe Package -> Qualification -> [SubDecl] -> Maybe Html +subTable _ _ [] = Nothing +subTable pkg qual decls = Just $ table << aboves (concatMap subRow decls)    where      subRow (decl, mdoc, subs) =        (td ! [theclass "src"] << decl         <-> -       docElement td << fmap (docToHtml Nothing qual) mdoc) +       docElement td << fmap (docToHtml Nothing pkg qual) mdoc)        : map (cell . (td <<)) subs  -- | Sub table with source information (optional). -subTableSrc :: Qualification -> LinksInfo -> Bool -> [(SubDecl,Located DocName)] -> Maybe Html -subTableSrc _ _  _ [] = Nothing -subTableSrc qual lnks splice decls = Just $ table << aboves (concatMap subRow decls) +subTableSrc :: Maybe Package -> Qualification -> LinksInfo -> Bool +            -> [(SubDecl,Located DocName)] -> Maybe Html +subTableSrc _ _ _ _ [] = Nothing +subTableSrc pkg qual lnks splice decls = Just $ table << aboves (concatMap subRow decls)    where      subRow ((decl, mdoc, subs),L loc dn) =        (td ! [theclass "src clearfix"] <<          (thespan ! [theclass "inst-left"] << decl)          <+> linkHtml loc dn        <-> -      docElement td << fmap (docToHtml Nothing qual) mdoc +      docElement td << fmap (docToHtml Nothing pkg qual) mdoc        )        : map (cell . (td <<)) subs      linkHtml loc@(RealSrcSpan _) dn = links lnks loc splice dn @@ -170,49 +171,49 @@ subBlock [] = Nothing  subBlock hs = Just $ toHtml hs -subArguments :: Qualification -> [SubDecl] -> Html -subArguments qual = divSubDecls "arguments" "Arguments" . subTable qual +subArguments :: Maybe Package -> Qualification -> [SubDecl] -> Html +subArguments pkg qual = divSubDecls "arguments" "Arguments" . subTable pkg qual  subAssociatedTypes :: [Html] -> Html  subAssociatedTypes = divSubDecls "associated-types" "Associated Types" . subBlock -subConstructors :: Qualification -> [SubDecl] -> Html -subConstructors qual = divSubDecls "constructors" "Constructors" . subTable qual +subConstructors :: Maybe Package -> Qualification -> [SubDecl] -> Html +subConstructors pkg qual = divSubDecls "constructors" "Constructors" . subTable pkg qual -subPatterns :: Qualification -> [SubDecl] -> Html -subPatterns qual = divSubDecls "bundled-patterns" "Bundled Patterns" . subTable qual +subPatterns :: Maybe Package -> Qualification -> [SubDecl] -> Html +subPatterns pkg qual = divSubDecls "bundled-patterns" "Bundled Patterns" . subTable pkg qual -subFields :: Qualification -> [SubDecl] -> Html -subFields qual = divSubDecls "fields" "Fields" . subDlist qual +subFields :: Maybe Package -> Qualification -> [SubDecl] -> Html +subFields pkg qual = divSubDecls "fields" "Fields" . subDlist pkg qual -subEquations :: Qualification -> [SubDecl] -> Html -subEquations qual = divSubDecls "equations" "Equations" . subTable qual +subEquations :: Maybe Package -> Qualification -> [SubDecl] -> Html +subEquations pkg qual = divSubDecls "equations" "Equations" . subTable pkg qual  -- | Generate sub table for instance declarations, with source -subInstances :: Qualification +subInstances :: Maybe Package -> Qualification               -> String -- ^ Class name, used for anchor generation               -> LinksInfo -> Bool               -> [(SubDecl,Located DocName)] -> Html -subInstances qual nm lnks splice = maybe noHtml wrap . instTable +subInstances pkg qual nm lnks splice = maybe noHtml wrap . instTable    where      wrap contents = subSection (collapseDetails id_ DetailsOpen (summary +++ contents)) -    instTable = subTableSrc qual lnks splice +    instTable = subTableSrc pkg qual lnks splice      subSection = thediv ! [theclass "subs instances"]      summary = thesummary << "Instances"      id_ = makeAnchorId $ "i:" ++ nm -subOrphanInstances :: Qualification +subOrphanInstances :: Maybe Package -> Qualification                     -> LinksInfo -> Bool                     -> [(SubDecl,Located DocName)] -> Html -subOrphanInstances qual lnks splice  = maybe noHtml wrap . instTable +subOrphanInstances pkg qual lnks splice  = maybe noHtml wrap . instTable    where      wrap = ((h1 << "Orphan instances") +++) -    instTable = fmap (thediv ! [ identifier ("section." ++ id_) ] <<) . subTableSrc qual lnks splice +    instTable = fmap (thediv ! [ identifier ("section." ++ id_) ] <<) . subTableSrc pkg qual lnks splice      id_ = makeAnchorId $ "orphans" @@ -228,15 +229,17 @@ subInstHead iid hdr =  subInstDetails :: String -- ^ Instance unique id (for anchor generation)                 -> [Html] -- ^ Associated type contents                 -> [Html] -- ^ Method contents (pretty-printed signatures) +               -> Html   -- ^ Source module                 -> Html -subInstDetails iid ats mets = -    subInstSection iid << (subAssociatedTypes ats <+> subMethods mets) +subInstDetails iid ats mets mdl = +    subInstSection iid << (p mdl <+> subAssociatedTypes ats <+> subMethods mets)  subFamInstDetails :: String -- ^ Instance unique id (for anchor generation)                    -> Html   -- ^ Type or data family instance +                  -> Html   -- ^ Source module TODO: use this                    -> Html -subFamInstDetails iid fi = -    subInstSection iid << thediv ! [theclass "src"] << fi +subFamInstDetails iid fi mdl = +    subInstSection iid << (p mdl <+> (thediv ! [theclass "src"] << fi))  subInstSection :: String -- ^ Instance unique id (for anchor generation)                 -> Html diff --git a/haddock-api/src/Haddock/Backends/Xhtml/Names.hs b/haddock-api/src/Haddock/Backends/Xhtml/Names.hs index a84a55e8..574045e0 100644 --- a/haddock-api/src/Haddock/Backends/Xhtml/Names.hs +++ b/haddock-api/src/Haddock/Backends/Xhtml/Names.hs @@ -22,7 +22,7 @@ import Haddock.GhcUtils  import Haddock.Types  import Haddock.Utils -import Text.XHtml hiding ( name, title, p, quote ) +import Text.XHtml hiding ( name, p, quote )  import qualified Data.Map as M  import qualified Data.List as List @@ -147,17 +147,19 @@ linkId mdl mbName = linkIdOcc mdl (fmap nameOccName mbName) True  linkIdOcc :: Module -> Maybe OccName -> Bool -> Html -> Html  linkIdOcc mdl mbName insertAnchors =    if insertAnchors -  then anchor ! [href url] +  then anchor ! [href url, title ttl]    else id    where +    ttl = moduleNameString (moduleName mdl)      url = case mbName of        Nothing   -> moduleUrl mdl        Just name -> moduleNameUrl mdl name  linkIdOcc' :: ModuleName -> Maybe OccName -> Html -> Html -linkIdOcc' mdl mbName = anchor ! [href url] +linkIdOcc' mdl mbName = anchor ! [href url, title ttl]    where +    ttl = moduleNameString mdl      url = case mbName of        Nothing   -> moduleHtmlFile' mdl        Just name -> moduleNameUrl' mdl name diff --git a/haddock-api/src/Haddock/Convert.hs b/haddock-api/src/Haddock/Convert.hs index b4804758..4635c076 100644 --- a/haddock-api/src/Haddock/Convert.hs +++ b/haddock-api/src/Haddock/Convert.hs @@ -1,4 +1,3 @@ -  {-# LANGUAGE CPP, PatternGuards, TypeFamilies #-}  -----------------------------------------------------------------------------  -- | @@ -38,7 +37,7 @@ import Type  import TyCoRep  import TysPrim ( alphaTyVars )  import TysWiredIn ( listTyConName, starKindTyConName, unitTy ) -import PrelNames ( hasKey, eqTyConKey, funTyConKey, ipClassKey +import PrelNames ( hasKey, eqTyConKey, ipClassKey                   , tYPETyConKey, liftedRepDataConKey )  import Unique ( getUnique )  import Util ( chkAppend, compareLength, dropList, filterByList, filterOut @@ -168,7 +167,7 @@ synifyTyCon _coax tc                                                      -- algebraic data nor newtype:                                        , dd_ctxt = noLoc []                                        , dd_cType = Nothing -                                      , dd_kindSig = Just (synifyKindSig (tyConKind tc)) +                                      , dd_kindSig = synifyDataTyConReturnKind tc                                                 -- we have their kind accurately:                                        , dd_cons = []  -- No constructors                                        , dd_derivs = noLoc [] } @@ -223,7 +222,7 @@ synifyTyCon coax tc                             -- CoAxioms, not their TyCons      _ -> synifyName tc    tyvars = synifyTyVars (tyConVisibleTyVars tc) -  kindSig = Just (tyConKind tc) +  kindSig = synifyDataTyConReturnKind tc    -- The data constructors.    --    -- Any data-constructors not exported from the module that *defines* the @@ -249,7 +248,7 @@ synifyTyCon coax tc                      , dd_ND      = alg_nd                      , dd_ctxt    = alg_ctx                      , dd_cType   = Nothing -                    , dd_kindSig = fmap synifyKindSig kindSig +                    , dd_kindSig = kindSig                      , dd_cons    = cons                      , dd_derivs  = alg_deriv }   in case lefts consRaw of @@ -259,6 +258,27 @@ synifyTyCon coax tc                   , tcdDExt = DataDeclRn False placeHolderNamesTc }    dataConErrs -> Left $ unlines dataConErrs +-- In this module, every TyCon being considered has come from an interface +-- file. This means that when considering a data type constructor such as: +-- +--   data Foo (w :: *) (m :: * -> *) (a :: *) +-- +-- Then its tyConKind will be (* -> (* -> *) -> * -> *). But beware! We are +-- also rendering the type variables of Foo, so if we synify the tyConKind of +-- Foo in full, we will end up displaying this in Haddock: +-- +--   data Foo (w :: *) (m :: * -> *) (a :: *) +--     :: * -> (* -> *) -> * -> * +-- +-- Which is entirely wrong (#548). We only want to display the *return* kind, +-- which this function obtains. +synifyDataTyConReturnKind :: TyCon -> Maybe (LHsKind GhcRn) +synifyDataTyConReturnKind tc +  = case splitFunTys (tyConKind tc) of +      (_, ret_kind) +        | isLiftedTypeKind ret_kind -> Nothing -- Don't bother displaying :: * +        | otherwise                 -> Just (synifyKindSig ret_kind) +  synifyInjectivityAnn :: Maybe Name -> [TyVar] -> Injectivity                       -> Maybe (LInjectivityAnn GhcRn)  synifyInjectivityAnn Nothing _ _            = Nothing diff --git a/haddock-api/src/Haddock/Interface.hs b/haddock-api/src/Haddock/Interface.hs index cbdf81cb..a66745ea 100644 --- a/haddock-api/src/Haddock/Interface.hs +++ b/haddock-api/src/Haddock/Interface.hs @@ -1,4 +1,4 @@ -{-# LANGUAGE CPP #-} +{-# LANGUAGE CPP, OverloadedStrings #-}  -----------------------------------------------------------------------------  -- |  -- Module      :  Haddock.Interface @@ -60,6 +60,7 @@ import FastString (unpackFS)  import MonadUtils (liftIO)  import TcRnTypes (tcg_rdr_env)  import RdrName (plusGlobalRdrEnv) +import ErrUtils (withTiming)  #if defined(mingw32_HOST_OS)  import System.IO @@ -93,13 +94,15 @@ processModules verbosity modules flags extIfaces = do          filter (\i -> not $ OptHide `elem` ifaceOptions i) interfaces        mods = Set.fromList $ map ifaceMod interfaces    out verbosity verbose "Attaching instances..." -  interfaces' <- attachInstances (exportedNames, mods) interfaces instIfaceMap +  interfaces' <- {-# SCC attachInstances #-} +                 withTiming getDynFlags "attachInstances" (const ()) $ do +                   attachInstances (exportedNames, mods) interfaces instIfaceMap    out verbosity verbose "Building cross-linking environment..."    -- Combine the link envs of the external packages into one    let extLinks  = Map.unions (map ifLinkEnv extIfaces) -      homeLinks = buildHomeLinks interfaces -- Build the environment for the home -                                            -- package +      homeLinks = buildHomeLinks interfaces' -- Build the environment for the home +                                             -- package        links     = homeLinks `Map.union` extLinks    out verbosity verbose "Renaming interfaces..." @@ -155,7 +158,9 @@ createIfaces verbosity flags instIfaceMap mods = do    return (reverse ifaces)    where      f (ifaces, ifaceMap) modSummary = do -      x <- processModule verbosity modSummary flags ifaceMap instIfaceMap +      x <- {-# SCC processModule #-} +           withTiming getDynFlags "processModule" (const ()) $ do +             processModule verbosity modSummary flags ifaceMap instIfaceMap        return $ case x of          Just iface -> (iface:ifaces, Map.insert (ifaceMod iface) iface ifaceMap)          Nothing    -> (ifaces, ifaceMap) -- Boot modules don't generate ifaces. @@ -164,7 +169,7 @@ createIfaces verbosity flags instIfaceMap mods = do  processModule :: Verbosity -> ModSummary -> [Flag] -> IfaceMap -> InstIfaceMap -> Ghc (Maybe Interface)  processModule verbosity modsum flags modMap instIfaceMap = do    out verbosity verbose $ "Checking module " ++ moduleString (ms_mod modsum) ++ "..." -  tm <- loadModule =<< typecheckModule =<< parseModule modsum +  tm <- {-# SCC "parse/typecheck/load" #-} loadModule =<< typecheckModule =<< parseModule modsum    -- We need to modify the interactive context's environment so that when    -- Haddock later looks for instances, it also looks in the modules it @@ -179,8 +184,10 @@ processModule verbosity modsum flags modMap instIfaceMap = do    if not $ isBootSummary modsum then do      out verbosity verbose "Creating interface..." -    (interface, msg) <- runWriterGhc $ createInterface tm flags modMap instIfaceMap -    liftIO $ mapM_ putStrLn msg +    (interface, msgs) <- {-# SCC createIterface #-} +                        withTiming getDynFlags "createInterface" (const ()) $ do +                          runWriterGhc $ createInterface tm flags modMap instIfaceMap +    liftIO $ mapM_ putStrLn (nub msgs)      dflags <- getDynFlags      let (haddockable, haddocked) = ifaceHaddockCoverage interface          percentage = round (fromIntegral haddocked * 100 / fromIntegral haddockable :: Double) :: Int diff --git a/haddock-api/src/Haddock/Interface/AttachInstances.hs b/haddock-api/src/Haddock/Interface/AttachInstances.hs index 286907e5..bf50ded3 100644 --- a/haddock-api/src/Haddock/Interface/AttachInstances.hs +++ b/haddock-api/src/Haddock/Interface/AttachInstances.hs @@ -19,7 +19,6 @@ import Haddock.Types  import Haddock.Convert  import Haddock.GhcUtils -import Control.Applicative  import Control.Arrow hiding ((<+>))  import Data.List  import Data.Ord (comparing) @@ -70,7 +69,7 @@ attachInstances expInfo ifaces instIfaceMap = do  attachOrphanInstances :: ExportInfo -> Interface -> IfaceMap -> InstIfaceMap -> [ClsInst] -> [DocInstance GhcRn]  attachOrphanInstances expInfo iface ifaceMap instIfaceMap cls_instances = -  [ (synifyInstHead i, instLookup instDocMap n iface ifaceMap instIfaceMap, (L (getSrcSpan n) n)) +  [ (synifyInstHead i, instLookup instDocMap n iface ifaceMap instIfaceMap, (L (getSrcSpan n) n), Nothing)    | let is = [ (instanceSig i, getName i) | i <- cls_instances, isOrphan (is_orphan i) ]    , (i@(_,_,cls,tys), n) <- sortBy (comparing $ first instHead) is    , not $ isInstanceHidden expInfo cls tys @@ -92,7 +91,11 @@ attachToExportItem index expInfo iface ifaceMap instIfaceMap export =          let mb_instances  = lookupNameEnv index (tcdName d)              cls_instances = maybeToList mb_instances >>= fst              fam_instances = maybeToList mb_instances >>= snd -            fam_insts = [ (synifyFamInst i opaque, doc,spanNameE n (synifyFamInst i opaque) (L eSpan (tcdName d)) ) +            fam_insts = [ ( synifyFamInst i opaque +                          , doc +                          , spanNameE n (synifyFamInst i opaque) (L eSpan (tcdName d)) +                          , nameModule_maybe n +                          )                          | i <- sortBy (comparing instFam) fam_instances                          , let n = getName i                          , let doc = instLookup instDocMap n iface ifaceMap instIfaceMap @@ -100,14 +103,18 @@ attachToExportItem index expInfo iface ifaceMap instIfaceMap export =                          , not $ any (isTypeHidden expInfo) (fi_tys i)                          , let opaque = isTypeHidden expInfo (fi_rhs i)                          ] -            cls_insts = [ (synifyInstHead i, instLookup instDocMap n iface ifaceMap instIfaceMap, spanName n (synifyInstHead i) (L eSpan (tcdName d))) +            cls_insts = [ ( synifyInstHead i +                          , instLookup instDocMap n iface ifaceMap instIfaceMap +                          , spanName n (synifyInstHead i) (L eSpan (tcdName d)) +                          , nameModule_maybe n +                          )                          | let is = [ (instanceSig i, getName i) | i <- cls_instances ]                          , (i@(_,_,cls,tys), n) <- sortBy (comparing $ first instHead) is                          , not $ isInstanceHidden expInfo cls tys                          ]                -- fam_insts but with failing type fams filtered out -            cleanFamInsts = [ (fi, n, L l r) | (Right fi, n, L l (Right r)) <- fam_insts ] -            famInstErrs = [ errm | (Left errm, _, _) <- fam_insts ] +            cleanFamInsts = [ (fi, n, L l r, m) | (Right fi, n, L l (Right r), m) <- fam_insts ] +            famInstErrs = [ errm | (Left errm, _, _, _) <- fam_insts ]          in do            dfs <- getDynFlags            let mkBug = (text "haddock-bug:" <+>) . text diff --git a/haddock-api/src/Haddock/Interface/Create.hs b/haddock-api/src/Haddock/Interface/Create.hs index 78b5c36d..78242990 100644 --- a/haddock-api/src/Haddock/Interface/Create.hs +++ b/haddock-api/src/Haddock/Interface/Create.hs @@ -46,7 +46,6 @@ import Data.Traversable  import Avail hiding (avail)  import qualified Avail -import qualified Packages  import qualified Module  import qualified SrcLoc  import ConLike (ConLike(..)) @@ -55,10 +54,11 @@ import HscTypes  import Name  import NameSet  import NameEnv +import Packages   ( lookupModuleInAllPackages, PackageName(..) )  import Bag  import RdrName  import TcRnTypes -import FastString (fastStringToByteString) +import FastString ( unpackFS, fastStringToByteString)  import BasicTypes ( StringLiteral(..), SourceText(..) )  import qualified Outputable as O  import HsDecls ( getConArgs ) @@ -85,12 +85,22 @@ createInterface tm flags modMap instIfaceMap = do        !instances     = modInfoInstances mi        !fam_instances = md_fam_insts md        !exportedNames = modInfoExportsWithSelectors mi +      (pkgNameFS, _) = modulePackageInfo dflags flags mdl +      pkgName        = fmap (unpackFS . (\(PackageName n) -> n)) pkgNameFS        (TcGblEnv { tcg_rdr_env = gre                  , tcg_warns   = warnings                  , tcg_exports = all_exports                  }, md) = tm_internals_ tm +  -- The 'pkgName' is necessary to decide what package to mention in "@since" +  -- annotations. Not having it is not fatal though. +  -- +  -- Cabal can be trusted to pass the right flags, so this warning should be +  -- mostly encountered when running Haddock outside of Cabal. +  when (isNothing pkgName) $ +    liftErrMsg $ tell [ "Warning: Package name is not available." ] +    -- The renamed source should always be available to us, but it's best    -- to be on the safe side.    (group_, imports, mayExports, mayDocHeader) <- @@ -103,7 +113,7 @@ createInterface tm flags modMap instIfaceMap = do    opts <- liftErrMsg $ mkDocOpts (haddockOptions dflags) flags mdl    -- Process the top-level module header documentation. -  (!info, mbDoc) <- liftErrMsg $ processModuleHeader dflags gre safety mayDocHeader +  (!info, mbDoc) <- liftErrMsg $ processModuleHeader dflags pkgName gre safety mayDocHeader    let declsWithDocs = topDecls group_ @@ -130,13 +140,13 @@ createInterface tm flags modMap instIfaceMap = do    warningMap <- liftErrMsg (mkWarningMap dflags warnings gre exportedNames)    maps@(!docMap, !argMap, !declMap, _) <- -    liftErrMsg (mkMaps dflags gre localInsts declsWithDocs) +    liftErrMsg (mkMaps dflags pkgName gre localInsts declsWithDocs)    let allWarnings = M.unions (warningMap : map ifaceWarningMap (M.elems modMap))    -- The MAIN functionality: compute the export items which will    -- each be the actual documentation of this module. -  exportItems <- mkExportItems is_sig modMap mdl sem_mdl allWarnings gre +  exportItems <- mkExportItems is_sig modMap pkgName mdl sem_mdl allWarnings gre                     exportedNames decls maps fixMap unrestrictedImportedMods                     splices exports all_exports instIfaceMap dflags @@ -160,7 +170,7 @@ createInterface tm flags modMap instIfaceMap = do    modWarn <- liftErrMsg (moduleWarning dflags gre warnings) -  tokenizedSrc <- mkMaybeTokenizedSrc flags tm +  tokenizedSrc <- mkMaybeTokenizedSrc dflags flags tm    return $! Interface {      ifaceMod               = mdl @@ -190,6 +200,7 @@ createInterface tm flags modMap instIfaceMap = do    , ifaceTokenizedSrc      = tokenizedSrc    } +  -- | Given all of the @import M as N@ declarations in a package,  -- create a mapping from the module identity of M, to an alias N  -- (if there are multiple aliases, we pick the last one.)  This @@ -266,7 +277,7 @@ lookupModuleDyn ::  lookupModuleDyn _ (Just pkgId) mdlName =    Module.mkModule pkgId mdlName  lookupModuleDyn dflags Nothing mdlName = -  case Packages.lookupModuleInAllPackages dflags mdlName of +  case lookupModuleInAllPackages dflags mdlName of      (m,_):_ -> m      [] -> Module.mkModule Module.mainUnitId mdlName @@ -314,16 +325,17 @@ mkDocOpts mbOpts flags mdl = do        [] -> tell ["No option supplied to DOC_OPTION/doc_option"] >> return []        xs -> liftM catMaybes (mapM parseOption xs)      Nothing -> return [] -  hm <- if Flag_HideModule (moduleString mdl) `elem` flags -        then return $ OptHide : opts -        else return opts -  ie <- if Flag_IgnoreAllExports `elem` flags -        then return $ OptIgnoreExports : hm -        else return hm -  se <- if Flag_ShowExtensions (moduleString mdl) `elem` flags -        then return $ OptShowExtensions : ie -        else return ie -  return se +  pure (foldl go opts flags) +  where +    mdlStr = moduleString mdl + +    -- Later flags override earlier ones +    go os m | m == Flag_HideModule mdlStr     = OptHide : os +            | m == Flag_ShowModule mdlStr     = filter (/= OptHide) os +            | m == Flag_ShowAllModules        = filter (/= OptHide) os +            | m == Flag_IgnoreAllExports      = OptIgnoreExports : os +            | m == Flag_ShowExtensions mdlStr = OptIgnoreExports : os +            | otherwise                       = os  parseOption :: String -> ErrMsgM (Maybe DocOption)  parseOption "hide"            = return (Just OptHide) @@ -345,11 +357,12 @@ type Maps = (DocMap Name, ArgMap Name, DeclMap, InstMap)  -- find its names, its subordinates, and its doc strings. Process doc strings  -- into 'Doc's.  mkMaps :: DynFlags +       -> Maybe Package  -- this package         -> GlobalRdrEnv         -> [Name]         -> [(LHsDecl GhcRn, [HsDocString])]         -> ErrMsgM Maps -mkMaps dflags gre instances decls = do +mkMaps dflags pkgName gre instances decls = do    (a, b, c) <- unzip3 <$> traverse mappings decls    pure ( f' (map (nubByName fst) a)         , f  (filterMapping (not . M.null) b) @@ -376,8 +389,8 @@ mkMaps dflags gre instances decls = do            declDoc :: [HsDocString] -> Map Int HsDocString                    -> ErrMsgM (Maybe (MDoc Name), Map Int (MDoc Name))            declDoc strs m = do -            doc' <- processDocStrings dflags gre strs -            m'   <- traverse (processDocStringParas dflags gre) m +            doc' <- processDocStrings dflags pkgName gre strs +            m'   <- traverse (processDocStringParas dflags pkgName gre) m              pure (doc', m')        (doc, args) <- declDoc docStrs (declTypeDocs decl) @@ -515,7 +528,8 @@ classDecls class_ = filterDecls . collectDocs . sortByLoc $ decls  -- | The top-level declarations of a module that we care about,  -- ordered by source location, with documentation attached if it exists.  topDecls :: HsGroup GhcRn -> [(LHsDecl GhcRn, [HsDocString])] -topDecls = filterClasses . filterDecls . collectDocs . sortByLoc . ungroup +topDecls = +  filterClasses . filterDecls . collectDocs . sortByLoc . ungroup  -- | Extract a map of fixity declarations only  mkFixMap :: HsGroup GhcRn -> FixMap @@ -575,7 +589,6 @@ filterDecls = filter (isHandled . unL . fst)      isHandled (DocD {})   = True      isHandled _ = False -  -- | Go through all class declarations and filter their sub-declarations  filterClasses :: [(LHsDecl a, doc)] -> [(LHsDecl a, doc)]  filterClasses decls = [ if isClassD d then (L loc (filterClass d), doc) else x @@ -620,12 +633,13 @@ collectDocs = go Nothing []  mkExportItems    :: Bool               -- is it a signature    -> IfaceMap +  -> Maybe Package      -- this package    -> Module             -- this module    -> Module             -- semantic module    -> WarningMap    -> GlobalRdrEnv    -> [Name]             -- exported names (orig) -  -> [LHsDecl GhcRn]     -- renamed source declarations +  -> [LHsDecl GhcRn]    -- renamed source declarations    -> Maps    -> FixMap    -> M.Map ModuleName [ModuleName] @@ -636,13 +650,14 @@ mkExportItems    -> DynFlags    -> ErrMsgGhc [ExportItem GhcRn]  mkExportItems -  is_sig modMap thisMod semMod warnings gre exportedNames decls +  is_sig modMap pkgName thisMod semMod warnings gre exportedNames decls    maps fixMap unrestricted_imp_mods splices exportList allExports    instIfaceMap dflags =    case exportList of      Nothing      -> -      fullModuleContents is_sig modMap thisMod semMod warnings exportedNames -        decls maps fixMap splices instIfaceMap dflags allExports +      fullModuleContents is_sig modMap pkgName thisMod semMod warnings gre +        exportedNames decls maps fixMap splices instIfaceMap dflags +        allExports      Just exports -> liftM concat $ mapM lookupExport exports    where      lookupExport (IEGroup _ lev docStr, _)  = liftErrMsg $ do @@ -650,14 +665,14 @@ mkExportItems        return [ExportGroup lev "" doc]      lookupExport (IEDoc _ docStr, _)        = liftErrMsg $ do -      doc <- processDocStringParas dflags gre docStr +      doc <- processDocStringParas dflags pkgName gre docStr        return [ExportDoc doc]      lookupExport (IEDocNamed _ str, _)      = liftErrMsg $        findNamedDoc str [ unL d | d <- decls ] >>= \case          Nothing -> return  []          Just docStr -> do -          doc <- processDocStringParas dflags gre docStr +          doc <- processDocStringParas dflags pkgName gre docStr            return [ExportDoc doc]      lookupExport (IEModuleContents _ (L _ mod_name), _) @@ -976,9 +991,11 @@ moduleExport thisMod dflags ifaceMap instIfaceMap expMod =  fullModuleContents :: Bool               -- is it a signature                     -> IfaceMap +                   -> Maybe Package      -- this package                     -> Module             -- this module                     -> Module             -- semantic module                     -> WarningMap +                   -> GlobalRdrEnv      -- ^ The renaming environment                     -> [Name]             -- exported names (orig)                     -> [LHsDecl GhcRn]    -- renamed source declarations                     -> Maps @@ -988,23 +1005,29 @@ fullModuleContents :: Bool               -- is it a signature                     -> DynFlags                     -> Avails                     -> ErrMsgGhc [ExportItem GhcRn] -fullModuleContents is_sig modMap thisMod semMod warnings exportedNames +fullModuleContents is_sig modMap pkgName thisMod semMod warnings gre exportedNames    decls maps@(_, _, declMap, _) fixMap splices instIfaceMap dflags avails = do    let availEnv = availsToNameEnv (nubAvails avails)    (concat . concat) `fmap` (for decls $ \decl -> do -    for (getMainDeclBinder (unLoc decl)) $ \nm -> do -      case lookupNameEnv availEnv nm of -        Just avail -          | L _ (ValD _ valDecl) <- decl -          , (name:_) <- collectHsBindBinders valDecl -          , Just (L _ SigD{}:_) <- filter isSigD <$> M.lookup name declMap -          -> pure [] - -          | otherwise -          -> availExportItem is_sig modMap thisMod -               semMod warnings exportedNames maps fixMap -               splices instIfaceMap dflags avail -        Nothing -> pure []) +    case decl of +      (L _ (DocD _ (DocGroup lev docStr))) -> do +        doc <- liftErrMsg (processDocString dflags gre docStr) +        return [[ExportGroup lev "" doc]] +      (L _ (DocD _ (DocCommentNamed _ docStr))) -> do +        doc <- liftErrMsg (processDocStringParas dflags pkgName gre docStr) +        return [[ExportDoc doc]] +      (L _ (ValD _ valDecl)) +        | name:_ <- collectHsBindBinders valDecl +        , Just (L _ SigD{}:_) <- filter isSigD <$> M.lookup name declMap +        -> return [] +      _ -> +        for (getMainDeclBinder (unLoc decl)) $ \nm -> do +          case lookupNameEnv availEnv nm of +            Just avail -> +              availExportItem is_sig modMap thisMod +                semMod warnings exportedNames maps fixMap +                splices instIfaceMap dflags avail +            Nothing -> pure [])    where      isSigD (L _ SigD{}) = True      isSigD _            = False @@ -1061,19 +1084,32 @@ extractDecl declMap name decl                               FamEqn { feqn_tycon = L _ n                                      , feqn_pats  = tys                                      , feqn_rhs   = defn }}))) -> -        SigD noExt <$> extractRecSel name n tys (dd_cons defn) -      InstD _ (ClsInstD _ ClsInstDecl { cid_datafam_insts = insts }) -> -        let matches = [ d' | L _ d'@(DataFamInstDecl (HsIB { hsib_body = d })) -                               <- insts -                             -- , L _ ConDecl { con_details = RecCon rec } <- dd_cons (feqn_rhs d) -                           , RecCon rec <- map (getConArgs . unLoc) (dd_cons (feqn_rhs d)) -                           , ConDeclField { cd_fld_names = ns } <- map unLoc (unLoc rec) -                           , L _ n <- ns -                           , extFieldOcc n == name -                      ] -        in case matches of -          [d0] -> extractDecl declMap name (noLoc . InstD noExt $ DataFamInstD noExt d0) -          _ -> error "internal: extractDecl (ClsInstD)" +        if isDataConName name +        then SigD noExt <$> extractPatternSyn name n tys (dd_cons defn) +        else SigD noExt <$> extractRecSel name n tys (dd_cons defn) +      InstD _ (ClsInstD _ ClsInstDecl { cid_datafam_insts = insts }) +        | isDataConName name -> +            let matches = [ d' | L _ d'@(DataFamInstDecl (HsIB { hsib_body = +                                          FamEqn { feqn_rhs   = dd +                                                 } +                                         })) <- insts +                               , name `elem` map unLoc (concatMap (getConNames . unLoc) (dd_cons dd)) +                               ] +            in case matches of +                [d0] -> extractDecl declMap name (noLoc (InstD noExt (DataFamInstD noExt d0))) +                _    -> error "internal: extractDecl (ClsInstD)" +        | otherwise -> +            let matches = [ d' | L _ d'@(DataFamInstDecl (HsIB { hsib_body = d })) +                                   <- insts +                                 -- , L _ ConDecl { con_details = RecCon rec } <- dd_cons (feqn_rhs d) +                               , RecCon rec <- map (getConArgs . unLoc) (dd_cons (feqn_rhs d)) +                               , ConDeclField { cd_fld_names = ns } <- map unLoc (unLoc rec) +                               , L _ n <- ns +                               , extFieldOcc n == name +                          ] +            in case matches of +              [d0] -> extractDecl declMap name (noLoc . InstD noExt $ DataFamInstD noExt d0) +              _ -> error "internal: extractDecl (ClsInstD)"        _ -> error "internal: extractDecl" @@ -1153,12 +1189,12 @@ seqList :: [a] -> ()  seqList [] = ()  seqList (x : xs) = x `seq` seqList xs -mkMaybeTokenizedSrc :: [Flag] -> TypecheckedModule +mkMaybeTokenizedSrc :: DynFlags -> [Flag] -> TypecheckedModule                      -> ErrMsgGhc (Maybe [RichToken]) -mkMaybeTokenizedSrc flags tm +mkMaybeTokenizedSrc dflags flags tm      | Flag_HyperlinkedSource `elem` flags = case renamedSource tm of          Just src -> do -            tokens <- liftGhcToErrMsgGhc . liftIO $ mkTokenizedSrc summary src +            tokens <- liftGhcToErrMsgGhc (liftIO (mkTokenizedSrc dflags summary src))              return $ Just tokens          Nothing -> do              liftErrMsg . tell . pure $ concat @@ -1171,12 +1207,15 @@ mkMaybeTokenizedSrc flags tm    where      summary = pm_mod_summary . tm_parsed_module $ tm -mkTokenizedSrc :: ModSummary -> RenamedSource -> IO [RichToken] -mkTokenizedSrc ms src = do +mkTokenizedSrc :: DynFlags -> ModSummary -> RenamedSource -> IO [RichToken] +mkTokenizedSrc dflags ms src = do    -- make sure to read the whole file at once otherwise    -- we run out of file descriptors (see #495)    rawSrc <- BS.readFile (msHsFilePath ms) >>= evaluate -  return $ Hyperlinker.enrich src (Hyperlinker.parse (decodeUtf8 rawSrc)) +  let tokens = Hyperlinker.parse dflags filepath (Utf8.decodeUtf8 rawSrc) +  return $ Hyperlinker.enrich src tokens +  where +    filepath = msHsFilePath ms  -- | Find a stand-alone documentation comment by its name.  findNamedDoc :: String -> [HsDecl GhcRn] -> ErrMsgM (Maybe HsDocString) diff --git a/haddock-api/src/Haddock/Interface/LexParseRn.hs b/haddock-api/src/Haddock/Interface/LexParseRn.hs index ce1dbc62..731f2a35 100644 --- a/haddock-api/src/Haddock/Interface/LexParseRn.hs +++ b/haddock-api/src/Haddock/Interface/LexParseRn.hs @@ -18,50 +18,48 @@ module Haddock.Interface.LexParseRn    , processModuleHeader    ) where -import Data.IntSet (toList)  import Data.List  import Documentation.Haddock.Doc (metaDocConcat)  import DynFlags (languageExtensions)  import qualified GHC.LanguageExtensions as LangExt -import FastString  import GHC  import Haddock.Interface.ParseModuleHeader  import Haddock.Parser  import Haddock.Types  import Name -import Outputable ( showPpr ) +import Outputable ( showPpr, showSDoc )  import RdrName  import EnumSet  import RnEnv (dataTcOccs) -processDocStrings :: DynFlags -> GlobalRdrEnv -> [HsDocString] +processDocStrings :: DynFlags -> Maybe Package -> GlobalRdrEnv -> [HsDocString]                    -> ErrMsgM (Maybe (MDoc Name)) -processDocStrings dflags gre strs = do -  mdoc <- metaDocConcat <$> traverse (processDocStringParas dflags gre) strs +processDocStrings dflags pkg gre strs = do +  mdoc <- metaDocConcat <$> traverse (processDocStringParas dflags pkg gre) strs    case mdoc of      -- We check that we don't have any version info to render instead      -- of just checking if there is no comment: there may not be a      -- comment but we still want to pass through any meta data. -    MetaDoc { _meta = Meta { _version = Nothing }, _doc = DocEmpty } -> pure Nothing +    MetaDoc { _meta = Meta Nothing Nothing, _doc = DocEmpty } -> pure Nothing      x -> pure (Just x) -processDocStringParas :: DynFlags -> GlobalRdrEnv -> HsDocString -> ErrMsgM (MDoc Name) -processDocStringParas dflags gre hds = -  overDocF (rename dflags gre) $ parseParas dflags (unpackHDS hds) +processDocStringParas :: DynFlags -> Maybe Package -> GlobalRdrEnv -> HsDocString -> ErrMsgM (MDoc Name) +processDocStringParas dflags pkg gre hds = +  overDocF (rename dflags gre) $ parseParas dflags pkg (unpackHDS hds)  processDocString :: DynFlags -> GlobalRdrEnv -> HsDocString -> ErrMsgM (Doc Name)  processDocString dflags gre hds =    rename dflags gre $ parseString dflags (unpackHDS hds) -processModuleHeader :: DynFlags -> GlobalRdrEnv -> SafeHaskellMode -> Maybe LHsDocString +processModuleHeader :: DynFlags -> Maybe Package -> GlobalRdrEnv -> SafeHaskellMode -> Maybe LHsDocString                      -> ErrMsgM (HaddockModInfo Name, Maybe (MDoc Name)) -processModuleHeader dflags gre safety mayStr = do +processModuleHeader dflags pkgName gre safety mayStr = do    (hmi, doc) <-      case mayStr of        Nothing -> return failure        Just (L _ hds) -> do          let str = unpackHDS hds -            (hmi, doc) = parseModuleHeader dflags str +            (hmi, doc) = parseModuleHeader dflags pkgName str          !descr <- case hmi_description hmi of                      Just hmi_descr -> Just <$> rename dflags gre hmi_descr                      Nothing        -> pure Nothing @@ -104,7 +102,9 @@ rename dflags gre = rn            -- We found no names in the env so we start guessing.            [] ->              case choices of +              -- This shouldn't happen as 'dataTcOccs' always returns at least its input.                [] -> pure (DocMonospaced (DocString (showPpr dflags x))) +                -- There was nothing in the environment so we need to                -- pick some default from what's available to us. We                -- diverge here from the old way where we would default @@ -113,16 +113,16 @@ rename dflags gre = rn                -- type constructor names (such as in #253). So now we                -- only get type constructor links if they are actually                -- in scope. -              a:_ -> pure (outOfScope dflags a) +              a:_ -> outOfScope dflags a            -- There is only one name in the environment that matches so            -- use it.            [a] -> pure (DocIdentifier a) +            -- But when there are multiple names available, default to            -- type constructors: somewhat awfully GHC returns the            -- values in the list positionally. -          a:b:_ | isTyConName a -> pure (DocIdentifier a) -                | otherwise -> pure (DocIdentifier b) +          a:b:_ -> ambiguous dflags x (if isTyConName a then a else b) names        DocWarning doc -> DocWarning <$> rn doc        DocEmphasis doc -> DocEmphasis <$> rn doc @@ -144,6 +144,7 @@ rename dflags gre = rn        DocEmpty -> pure (DocEmpty)        DocString str -> pure (DocString str)        DocHeader (Header l t) -> DocHeader . Header l <$> rn t +      DocTable t -> DocTable <$> traverse rn t  -- | Wrap an identifier that's out of scope (i.e. wasn't found in  -- 'GlobalReaderEnv' during 'rename') in an appropriate doc. Currently @@ -153,12 +154,29 @@ rename dflags gre = rn  -- 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'. -outOfScope :: DynFlags -> RdrName -> Doc a +outOfScope :: DynFlags -> RdrName -> ErrMsgM (Doc a)  outOfScope dflags x =    case x of -    Unqual occ -> monospaced occ -    Qual mdl occ -> DocIdentifierUnchecked (mdl, occ) -    Orig _ occ -> monospaced occ -    Exact name -> monospaced name  -- Shouldn't happen since x is out of scope +    Unqual occ -> warnAndMonospace occ +    Qual mdl occ -> pure (DocIdentifierUnchecked (mdl, occ)) +    Orig _ occ -> warnAndMonospace occ +    Exact name -> warnAndMonospace name  -- Shouldn't happen since x is out of scope    where +    warnAndMonospace a = do +      tell ["Warning: '" ++ showPpr dflags a ++ "' is out of scope."] +      pure (monospaced a)      monospaced a = DocMonospaced (DocString (showPpr dflags a)) + +-- | Warn about an ambiguous identifier. +ambiguous :: DynFlags -> RdrName -> Name -> [Name] -> ErrMsgM (Doc Name) +ambiguous dflags x dflt names = do +  tell [msg] +  pure (DocIdentifier dflt) +  where +    msg = "Warning: " ++ x_str ++ " is ambiguous. It is defined\n" ++ +          concatMap (\n -> "    * " ++ defnLoc n ++ "\n") names ++ +          "    You may be able to disambiguate the identifier by qualifying it or\n" ++ +          "    by hiding some imports.\n" ++ +          "    Defaulting to " ++ x_str ++ " defined " ++ defnLoc dflt +    x_str = '\'' : showPpr dflags x ++ "'" +    defnLoc = showSDoc dflags . pprNameDefnLoc diff --git a/haddock-api/src/Haddock/Interface/ParseModuleHeader.hs b/haddock-api/src/Haddock/Interface/ParseModuleHeader.hs index 768a31ce..050901b6 100644 --- a/haddock-api/src/Haddock/Interface/ParseModuleHeader.hs +++ b/haddock-api/src/Haddock/Interface/ParseModuleHeader.hs @@ -24,8 +24,8 @@ import RdrName  -- NB.  The headers must be given in the order Module, Description,  -- Copyright, License, Maintainer, Stability, Portability, except that  -- any or all may be omitted. -parseModuleHeader :: DynFlags -> String -> (HaddockModInfo RdrName, MDoc RdrName) -parseModuleHeader dflags str0 = +parseModuleHeader :: DynFlags -> Maybe Package -> String -> (HaddockModInfo RdrName, MDoc RdrName) +parseModuleHeader dflags pkgName str0 =     let        getKey :: String -> String -> (Maybe String,String)        getKey key str = case parseKey key str of @@ -37,21 +37,22 @@ parseModuleHeader dflags str0 =        (copyrightOpt,str3) = getKey "Copyright" str2        (licenseOpt,str4) = getKey "License" str3        (licenceOpt,str5) = getKey "Licence" str4 -      (maintainerOpt,str6) = getKey "Maintainer" str5 -      (stabilityOpt,str7) = getKey "Stability" str6 -      (portabilityOpt,str8) = getKey "Portability" str7 +      (spdxLicenceOpt,str6) = getKey "SPDX-License-Identifier" str5 +      (maintainerOpt,str7) = getKey "Maintainer" str6 +      (stabilityOpt,str8) = getKey "Stability" str7 +      (portabilityOpt,str9) = getKey "Portability" str8     in (HaddockModInfo {            hmi_description = parseString dflags <$> descriptionOpt,            hmi_copyright = copyrightOpt, -          hmi_license = licenseOpt `mplus` licenceOpt, +          hmi_license = spdxLicenceOpt `mplus` licenseOpt `mplus` licenceOpt,            hmi_maintainer = maintainerOpt,            hmi_stability = stabilityOpt,            hmi_portability = portabilityOpt,            hmi_safety = Nothing,            hmi_language = Nothing, -- set in LexParseRn            hmi_extensions = [] -- also set in LexParseRn -          }, parseParas dflags str8) +          }, parseParas dflags pkgName str9)  -- | This function is how we read keys.  -- diff --git a/haddock-api/src/Haddock/Interface/Rename.hs b/haddock-api/src/Haddock/Interface/Rename.hs index e3e4e987..c07f8300 100644 --- a/haddock-api/src/Haddock/Interface/Rename.hs +++ b/haddock-api/src/Haddock/Interface/Rename.hs @@ -22,6 +22,8 @@ import Bag (emptyBag)  import GHC hiding (NoLink)  import Name  import Outputable ( panic ) +import RdrName (RdrName(Exact)) +import PrelNames (eqTyCon_RDR)  import Control.Applicative  import Control.Monad hiding (mapM) @@ -60,11 +62,18 @@ renameInterface dflags renamingEnv warnings iface =                      (missingNames1 ++ missingNames2 ++ missingNames3                       ++ missingNames4 ++ missingNames5) -      -- filter out certain built in type constructors using their string -      -- representation. TODO: use the Name constants from the GHC API. ---      strings = filter (`notElem` ["()", "[]", "(->)"]) ---                (map pretty missingNames) -      strings = map (pretty dflags) . filter (\n -> not (isSystemName n || isBuiltInSyntax n)) $ missingNames +      -- Filter out certain built in type constructors using their string +      -- representation. +      -- +      -- Note that since the renamed AST represents equality constraints as +      -- @HasOpTy t1 eqTyCon_RDR t2@ (and _not_ as @HsEqTy t1 t2@), we need to +      -- manually filter out 'eqTyCon_RDR' (aka @~@). +      strings = [ pretty dflags n +                | n <- missingNames +                , not (isSystemName n) +                , not (isBuiltInSyntax n) +                , Exact n /= eqTyCon_RDR +                ]    in do      -- report things that we couldn't link to. Only do this for non-hidden @@ -263,11 +272,22 @@ renameType t = case t of    HsRecTy _ a               -> HsRecTy NoExt <$> mapM renameConDeclFieldField a    (XHsType (NHsCoreTy a))   -> pure (XHsType (NHsCoreTy a)) -  HsExplicitListTy x i b    -> HsExplicitListTy x i <$> mapM renameLType b -  HsExplicitTupleTy x b     -> HsExplicitTupleTy x <$> mapM renameLType b -  HsSpliceTy _ _            -> error "renameType: HsSpliceTy" -  HsWildCardTy a            -> HsWildCardTy <$> renameWildCardInfo a -  HsAppsTy _ _              -> error "renameType: HsAppsTy" +  HsExplicitListTy i a b  -> HsExplicitListTy i a <$> mapM renameLType b +  HsExplicitTupleTy a b   -> HsExplicitTupleTy a <$> mapM renameLType b +  HsSpliceTy _ s          -> renameHsSpliceTy s +  HsWildCardTy a          -> HsWildCardTy <$> renameWildCardInfo a +  HsAppsTy _ _            -> error "renameType: HsAppsTy" + +-- | Rename splices, but _only_ those that turn out to be for types. +-- I think this is actually safe for our possible inputs: +-- +--  * the input is from after GHC's renamer, so should have an 'HsSpliced' +--  * the input is typechecked, and only 'HsSplicedTy' should get through that +-- +renameHsSpliceTy :: HsSplice GhcRn -> RnM (HsType DocNameI) +renameHsSpliceTy (HsSpliced _ _ (HsSplicedTy t)) = renameType t +renameHsSpliceTy (HsSpliced _ _ _) = error "renameHsSpliceTy: not an HsSplicedTy" +renameHsSpliceTy _ = error "renameHsSpliceTy: not an HsSpliced"  renameLHsQTyVars :: LHsQTyVars GhcRn -> RnM (LHsQTyVars DocNameI)  renameLHsQTyVars (HsQTvs { hsq_explicit = tvs }) @@ -644,11 +664,11 @@ renameWc rn_thing (HsWC { hswc_body = thing })  renameWc _ (XHsWildCardBndrs _) = panic "haddock:renameWc"  renameDocInstance :: DocInstance GhcRn -> RnM (DocInstance DocNameI) -renameDocInstance (inst, idoc, L l n) = do +renameDocInstance (inst, idoc, L l n, m) = do    inst' <- renameInstHead inst    n' <- rename n    idoc' <- mapM renameDoc idoc -  return (inst', idoc',L l n') +  return (inst', idoc', L l n', m)  renameExportItem :: ExportItem GhcRn -> RnM (ExportItem DocNameI)  renameExportItem item = case item of diff --git a/haddock-api/src/Haddock/Interface/Specialize.hs b/haddock-api/src/Haddock/Interface/Specialize.hs index 092a2f4e..2fcb495c 100644 --- a/haddock-api/src/Haddock/Interface/Specialize.hs +++ b/haddock-api/src/Haddock/Interface/Specialize.hs @@ -29,23 +29,23 @@ import qualified Data.Set as Set  -- | Instantiate all occurrences of given names with corresponding types.  specialize :: Data a => [(Name, HsType GhcRn)] -> a -> a -specialize specs = go +specialize specs = go spec_map0    where -    go :: forall x. Data x => x -> x -    go = everywhereButType @Name $ mkT $ sugar . strip_kind_sig . specialize_ty_var +    go :: forall x. Data x => Map Name (HsType GhcRn) -> x -> x +    go spec_map = everywhereButType @Name $ mkT $ sugar . strip_kind_sig . specialize_ty_var spec_map      strip_kind_sig :: HsType name -> HsType name      strip_kind_sig (HsKindSig _ (L _ t) _) = t      strip_kind_sig typ = typ -    specialize_ty_var :: HsType GhcRn -> HsType GhcRn -    specialize_ty_var (HsTyVar _ _ (L _ name')) +    specialize_ty_var :: Map Name (HsType GhcRn) -> HsType GhcRn -> HsType GhcRn +    specialize_ty_var spec_map (HsTyVar _ _ (L _ name'))        | Just t <- Map.lookup name' spec_map = t -    specialize_ty_var typ = typ -    -- This is a tricky recursive definition that is guaranteed to terminate -    -- because a type binder cannot be instantiated with a type that depends -    -- on that binder. i.e. @a -> Maybe a@ is invalid -    spec_map = Map.fromList [ (n, go t) | (n, t) <- specs] +    specialize_ty_var _ typ = typ + +    -- This is a tricky recursive definition. By adding in the specializations +    -- one by one, we should avoid infinite loops. +    spec_map0 = foldr (\(n,t) acc -> Map.insert n (go acc t) acc) mempty specs  -- | Instantiate given binders with corresponding types. diff --git a/haddock-api/src/Haddock/InterfaceFile.hs b/haddock-api/src/Haddock/InterfaceFile.hs index a4e9eb3c..ce6ecc78 100644 --- a/haddock-api/src/Haddock/InterfaceFile.hs +++ b/haddock-api/src/Haddock/InterfaceFile.hs @@ -83,7 +83,7 @@ binaryInterfaceMagic = 0xD0Cface  --  binaryInterfaceVersion :: Word16  #if (__GLASGOW_HASKELL__ >= 805) && (__GLASGOW_HASKELL__ < 807) -binaryInterfaceVersion = 32 +binaryInterfaceVersion = 33  binaryInterfaceVersionCompatibility :: [Word16]  binaryInterfaceVersionCompatibility = [binaryInterfaceVersion] @@ -459,9 +459,40 @@ instance Binary a => Binary (Header a) where          t <- get bh          return (Header l t) +instance Binary a => Binary (Table a) where +    put_ bh (Table h b) = do +        put_ bh h +        put_ bh b +    get bh = do +        h <- get bh +        b <- get bh +        return (Table h b) + +instance Binary a => Binary (TableRow a) where +    put_ bh (TableRow cs) = put_ bh cs +    get bh = do +        cs <- get bh +        return (TableRow cs) + +instance Binary a => Binary (TableCell a) where +    put_ bh (TableCell i j c) = do +        put_ bh i +        put_ bh j +        put_ bh c +    get bh = do +        i <- get bh +        j <- get bh +        c <- get bh +        return (TableCell i j c) +  instance Binary Meta where -  put_ bh Meta { _version = v } = put_ bh v -  get bh = (\v -> Meta { _version = v }) <$> get bh +    put_ bh (Meta v p) = do +        put_ bh v +        put_ bh p +    get bh = do +        v <- get bh +        p <- get bh +        return (Meta v p)  instance (Binary mod, Binary id) => Binary (MetaDoc mod id) where    put_ bh MetaDoc { _meta = m, _doc = d } = do @@ -542,6 +573,9 @@ instance (Binary mod, Binary id) => Binary (DocH mod id) where      put_ bh (DocMathDisplay x) = do              putByte bh 22              put_ bh x +    put_ bh (DocTable x) = do +            putByte bh 23 +            put_ bh x      get bh = do              h <- getByte bh @@ -615,6 +649,9 @@ instance (Binary mod, Binary id) => Binary (DocH mod id) where                22 -> do                      x <- get bh                      return (DocMathDisplay x) +              23 -> do +                    x <- get bh +                    return (DocTable x)                _ -> error "invalid binary data found in the interface file" diff --git a/haddock-api/src/Haddock/Options.hs b/haddock-api/src/Haddock/Options.hs index caf1fefe..b5e987d8 100644 --- a/haddock-api/src/Haddock/Options.hs +++ b/haddock-api/src/Haddock/Options.hs @@ -29,19 +29,23 @@ module Haddock.Options (    optLaTeXStyle,    optMathjax,    qualification, +  sinceQualification,    verbosity,    ghcFlags,    reexportFlags,    readIfaceArgs,    optPackageName, -  optPackageVersion +  optPackageVersion, +  modulePackageInfo  ) where  import qualified Data.Char as Char  import           Data.Version +import           Control.Applicative  import           Distribution.Verbosity  import           FastString +import           GHC ( DynFlags, Module, moduleUnitId )  import           Haddock.Types  import           Haddock.Utils  import           Packages @@ -86,6 +90,8 @@ data Flag    | Flag_GenIndex    | Flag_IgnoreAllExports    | Flag_HideModule String +  | Flag_ShowModule String +  | Flag_ShowAllModules    | Flag_ShowExtensions String    | Flag_OptGhc String    | Flag_GhcLibDir String @@ -101,6 +107,7 @@ data Flag    | Flag_PackageName String    | Flag_PackageVersion String    | Flag_Reexport String +  | Flag_SinceQualification String    deriving (Eq, Show) @@ -182,6 +189,10 @@ options backwardsCompat =        "behave as if all modules have the\nignore-exports atribute",      Option [] ["hide"] (ReqArg Flag_HideModule "MODULE")        "behave as if MODULE has the hide attribute", +    Option [] ["show"] (ReqArg Flag_ShowModule "MODULE") +      "behave as if MODULE does not have the hide attribute", +    Option [] ["show-all"] (NoArg Flag_ShowAllModules) +      "behave as if not modules have the hide attribute",      Option [] ["show-extensions"] (ReqArg Flag_ShowExtensions "MODULE")        "behave as if MODULE has the show-extensions attribute",      Option [] ["optghc"] (ReqArg Flag_OptGhc "OPTION") @@ -204,7 +215,9 @@ options backwardsCompat =      Option [] ["package-name"] (ReqArg Flag_PackageName "NAME")        "name of the package being documented",      Option [] ["package-version"] (ReqArg Flag_PackageVersion "VERSION") -      "version of the package being documented in usual x.y.z.w format" +      "version of the package being documented in usual x.y.z.w format", +    Option []  ["since-qual"] (ReqArg Flag_SinceQualification "QUAL") +      "package qualification of @since, one of\n'always' (default) or 'only-external'"    ] @@ -304,6 +317,14 @@ qualification flags =        [arg]          -> Left $ "unknown qualification type " ++ show arg        _:_            -> Left "qualification option given multiple times" +sinceQualification :: [Flag] -> Either String SinceQual +sinceQualification flags = +  case map (map Char.toLower) [ str | Flag_SinceQualification str <- flags ] of +      []             -> Right Always +      ["always"]     -> Right Always +      ["external"]   -> Right External +      [arg]          -> Left $ "unknown since-qualification type " ++ show arg +      _:_            -> Left "since-qualification option given multiple times"  verbosity :: [Flag] -> Verbosity  verbosity flags = @@ -338,3 +359,23 @@ readIfaceArgs flags = [ parseIfaceOption s | Flag_ReadInterface s <- flags ]  optLast :: [a] -> Maybe a  optLast [] = Nothing  optLast xs = Just (last xs) + + +-- | This function has a potential to return 'Nothing' because package name and +-- versions can no longer reliably be extracted in all cases: if the package is +-- not installed yet then this info is no longer available. +-- +-- The @--package-name@ and @--package-version@ Haddock flags allow the user to +-- specify this information manually and it is returned here if present. +modulePackageInfo :: DynFlags +                  -> [Flag] -- ^ Haddock flags are checked as they may contain +                            -- the package name or version provided by the user +                            -- which we prioritise +                  -> Module +                  -> (Maybe PackageName, Maybe Data.Version.Version) +modulePackageInfo dflags flags modu = +  ( optPackageName flags    <|> fmap packageName pkgDb +  , optPackageVersion flags <|> fmap packageVersion pkgDb +  ) +  where +    pkgDb = lookupPackage dflags (moduleUnitId modu) diff --git a/haddock-api/src/Haddock/Parser.hs b/haddock-api/src/Haddock/Parser.hs index 47bf814b..58500f1b 100644 --- a/haddock-api/src/Haddock/Parser.hs +++ b/haddock-api/src/Haddock/Parser.hs @@ -28,8 +28,8 @@ import RdrName (RdrName)  import SrcLoc (mkRealSrcLoc, unLoc)  import StringBuffer (stringToStringBuffer) -parseParas :: DynFlags -> String -> MetaDoc mod RdrName -parseParas d = overDoc (P.overIdentifier (parseIdent d)) . P.parseParas +parseParas :: DynFlags -> Maybe Package -> String -> MetaDoc mod RdrName +parseParas d p = overDoc (P.overIdentifier (parseIdent d)) . P.parseParas p  parseString :: DynFlags -> String -> DocH mod RdrName  parseString d = P.overIdentifier (parseIdent d) . P.parseString diff --git a/haddock-api/src/Haddock/Types.hs b/haddock-api/src/Haddock/Types.hs index 8e879cc8..a5ebfa42 100644 --- a/haddock-api/src/Haddock/Types.hs +++ b/haddock-api/src/Haddock/Types.hs @@ -38,8 +38,6 @@ import BasicTypes (Fixity(..))  import GHC hiding (NoLink)  import DynFlags (Language)  import qualified GHC.LanguageExtensions as LangExt -import Coercion -import NameSet  import OccName  import Outputable  import Control.Applicative (Applicative(..)) @@ -390,7 +388,7 @@ mkPseudoFamilyDecl (XFamilyDecl {}) = panic "haddock:mkPseudoFamilyDecl"  -- | An instance head that may have documentation and a source location. -type DocInstance name = (InstHead name, Maybe (MDoc (IdP name)), Located (IdP name)) +type DocInstance name = (InstHead name, Maybe (MDoc (IdP name)), Located (IdP name), Maybe Module)  -- | The head of an instance. Consists of a class name, a list of type  -- parameters (which may be annotated with kinds), and an instance type @@ -456,6 +454,7 @@ instance (NFData a, NFData mod)      DocProperty a             -> a `deepseq` ()      DocExamples a             -> a `deepseq` ()      DocHeader a               -> a `deepseq` () +    DocTable a                -> a `deepseq` ()  #if !MIN_VERSION_ghc(8,0,2)  -- These were added to GHC itself in 8.0.2 @@ -476,6 +475,14 @@ instance NFData Picture where  instance NFData Example where    rnf (Example a b) = a `deepseq` b `deepseq` () +instance NFData id => NFData (Table id) where +    rnf (Table h b) = h `deepseq` b `deepseq` () + +instance NFData id => NFData (TableRow id) where +    rnf (TableRow cs) = cs `deepseq` () + +instance NFData id => NFData (TableCell id) where +    rnf (TableCell i j c) = i `deepseq` j `deepseq` c `deepseq` ()  exampleToString :: Example -> String  exampleToString (Example expression result) = @@ -571,6 +578,12 @@ data HideEmptyContexts    = HideEmptyContexts    | ShowEmptyToplevelContexts +-- | When to qualify @since@ annotations with their package +data SinceQual +  = Always +  | External -- ^ only qualify when the thing being annotated is from +             -- an external package +  -----------------------------------------------------------------------------  -- * Error handling  ----------------------------------------------------------------------------- diff --git a/haddock-api/src/Haddock/Utils.hs b/haddock-api/src/Haddock/Utils.hs index e3cc9655..c2cdddf7 100644 --- a/haddock-api/src/Haddock/Utils.hs +++ b/haddock-api/src/Haddock/Utils.hs @@ -62,7 +62,6 @@ import Haddock.GhcUtils  import GHC  import Name -import NameSet ( emptyNameSet )  import HsTypes (extFieldOcc)  import Outputable ( panic ) diff --git a/haddock-api/test/Haddock/Backends/Hyperlinker/ParserSpec.hs b/haddock-api/test/Haddock/Backends/Hyperlinker/ParserSpec.hs index 8cd2690e..4639253c 100644 --- a/haddock-api/test/Haddock/Backends/Hyperlinker/ParserSpec.hs +++ b/haddock-api/test/Haddock/Backends/Hyperlinker/ParserSpec.hs @@ -4,95 +4,149 @@ module Haddock.Backends.Hyperlinker.ParserSpec (main, spec) where  import Test.Hspec  import Test.QuickCheck +import qualified GHC +import Control.Monad.IO.Class + +import Haddock (getGhcDirs)  import Haddock.Backends.Hyperlinker.Parser  import Haddock.Backends.Hyperlinker.Types +withDynFlags :: (GHC.DynFlags -> IO ()) -> IO () +withDynFlags cont = do +  libDir <- fmap snd (getGhcDirs []) +  GHC.runGhc (Just libDir) $ do +    dflags <- GHC.getSessionDynFlags +    liftIO $ cont dflags +  main :: IO ()  main = hspec spec  spec :: Spec -spec = do -    describe "parse" parseSpec +spec = describe "parse" parseSpec -parseSpec :: Spec -parseSpec = do +-- | Defined for its instance of 'Arbitrary'. Represents strings that, when +-- considered as GHC source, won't be rewritten. +newtype NoGhcRewrite = NoGhcRewrite String deriving (Show, Eq) -    it "is total" $ -        property $ \src -> length (parse src) `shouldSatisfy` (>= 0) +-- | Filter out strings where GHC would replace/remove some characters during +-- lexing. +noGhcRewrite :: String -> Bool +noGhcRewrite ('\t':_) = False        -- GHC replaces tabs with 8 spaces +noGhcRewrite ('\r':_) = False +noGhcRewrite ('\f':_) = False +noGhcRewrite ('\v':_) = False +noGhcRewrite (' ':'\n':_) = False    -- GHC strips whitespace on empty lines +noGhcRewrite (_:s) = noGhcRewrite s +noGhcRewrite "" = True -    it "retains file layout" $ -        property $ \src -> concatMap tkValue (parse src) == src +instance Arbitrary NoGhcRewrite where +  arbitrary = fmap NoGhcRewrite (arbitrary `suchThat` noGhcRewrite) +  shrink (NoGhcRewrite src) = [ NoGhcRewrite shrunk +                              | shrunk <- shrink src +                              , noGhcRewrite shrunk +                              ] -    context "when parsing single-line comments" $ do -        it "should ignore content until the end of line" $ -            "-- some very simple comment\nidentifier" -            `shouldParseTo` -            [TkComment, TkSpace, TkIdentifier] +parseSpec :: Spec +parseSpec = around withDynFlags $ do -        it "should allow endline escaping" $ -            "-- first line\\\nsecond line\\\nand another one" -            `shouldParseTo` -            [TkComment] +    it "is total" $ \dflags -> +        property $ \src -> length (parse dflags "" src) `shouldSatisfy` (>= 0) -    context "when parsing multi-line comments" $ do +    it "retains file layout" $ \dflags -> +        property $ \(NoGhcRewrite src) -> concatMap tkValue (parse dflags "" src) == src -        it "should support nested comments" $ -            "{- comment {- nested -} still comment -} {- next comment -}" -            `shouldParseTo` -            [TkComment, TkSpace, TkComment] +    context "when parsing single-line comments" $ do + +        it "should ignore content until the end of line" $ \dflags -> +            shouldParseTo +                "-- some very simple comment\nidentifier" +                [TkComment, TkSpace, TkIdentifier] +                dflags -        it "should distinguish compiler pragma" $ -            "{- comment -}{-# LANGUAGE GADTs #-}{- comment -}" -            `shouldParseTo` -            [TkComment, TkPragma, TkComment] +        it "should allow endline escaping" $ \dflags -> +            shouldParseTo +                "#define first line\\\nsecond line\\\nand another one" +                [TkCpp] +                dflags -    it "should recognize preprocessor directives" $ do -        "\n#define foo bar" `shouldParseTo` [TkSpace, TkCpp] -        "x # y" `shouldParseTo` -            [TkIdentifier, TkSpace, TkOperator, TkSpace,TkIdentifier] +    context "when parsing multi-line comments" $ do -    it "should distinguish basic language constructs" $ do -        "(* 2) <$> (\"abc\", foo)" `shouldParseTo` +        it "should support nested comments" $ \dflags -> +            shouldParseTo +                "{- comment {- nested -} still comment -} {- next comment -}" +                [TkComment, TkSpace, TkComment] +                dflags + +        it "should distinguish compiler pragma" $ \dflags -> +            shouldParseTo +                "{- comment -}{-# LANGUAGE GADTs #-}{- comment -}" +                [TkComment, TkPragma, TkComment] +                dflags + +    it "should recognize preprocessor directives" $ \dflags -> do +            shouldParseTo +                "\n#define foo bar" +                [TkSpace, TkCpp] +                dflags +            shouldParseTo +                "x # y" +                [TkIdentifier, TkSpace, TkOperator, TkSpace,TkIdentifier] +                dflags + +    it "should distinguish basic language constructs" $ \dflags -> do +         +        shouldParseTo +            "(* 2) <$> (\"abc\", foo)"              [ TkSpecial, TkOperator, TkSpace, TkNumber, TkSpecial              , TkSpace, TkOperator, TkSpace              , TkSpecial, TkString, TkSpecial, TkSpace, TkIdentifier, TkSpecial              ] -        "let foo' = foo in foo' + foo'" `shouldParseTo` +            dflags +             +        shouldParseTo +            "let foo' = foo in foo' + foo'"              [ TkKeyword, TkSpace, TkIdentifier              , TkSpace, TkGlyph, TkSpace              , TkIdentifier, TkSpace, TkKeyword, TkSpace              , TkIdentifier, TkSpace, TkOperator, TkSpace, TkIdentifier              ] -        "square x = y^2 where y = x" `shouldParseTo` +            dflags +         +        shouldParseTo +            "square x = y^2 where y = x"              [ TkIdentifier, TkSpace, TkIdentifier              , TkSpace, TkGlyph, TkSpace              , TkIdentifier, TkOperator, TkNumber              , TkSpace, TkKeyword, TkSpace              , TkIdentifier, TkSpace, TkGlyph, TkSpace, TkIdentifier              ] +            dflags -    it "should parse do-notation syntax" $ do -        "do { foo <- getLine; putStrLn foo }" `shouldParseTo` +    it "should parse do-notation syntax" $ \dflags -> do +        shouldParseTo +            "do { foo <- getLine; putStrLn foo }"              [ TkKeyword, TkSpace, TkSpecial, TkSpace              , TkIdentifier, TkSpace, TkGlyph, TkSpace              , TkIdentifier, TkSpecial, TkSpace              , TkIdentifier, TkSpace, TkIdentifier, TkSpace, TkSpecial              ] - -        unlines -            [ "do" -            , "    foo <- getLine" -            , "    putStrLn foo" -            ] `shouldParseTo` +            dflags + +        shouldParseTo +            (unlines +                [ "do" +                , "    foo <- getLine" +                , "    putStrLn foo" +                ])              [ TkKeyword, TkSpace, TkIdentifier              , TkSpace, TkGlyph, TkSpace, TkIdentifier, TkSpace              , TkIdentifier, TkSpace, TkIdentifier, TkSpace              ] - - -shouldParseTo :: String -> [TokenType] -> Expectation -str `shouldParseTo` tokens = map tkType (parse str) `shouldBe` tokens +            dflags +  where +    shouldParseTo :: String -> [TokenType] -> GHC.DynFlags -> Expectation +    shouldParseTo str tokens dflags = map tkType (parse dflags "" str) `shouldBe` tokens | 
