diff options
Diffstat (limited to 'haddock-api')
40 files changed, 1983 insertions, 1133 deletions
diff --git a/haddock-api/.ghci b/haddock-api/.ghci deleted file mode 100644 index 62e7c5d2..00000000 --- a/haddock-api/.ghci +++ /dev/null @@ -1 +0,0 @@ -:set -isrc -idist/build -idist/build/autogen -optP-include -optPdist/build/autogen/cabal_macros.h diff --git a/haddock-api/haddock-api.cabal b/haddock-api/haddock-api.cabal index 87761ff8..52191e13 100644 --- a/haddock-api/haddock-api.cabal +++ b/haddock-api/haddock-api.cabal @@ -1,6 +1,6 @@  cabal-version:        2.0  name:                 haddock-api -version:              2.22.0 +version:              2.24.0  synopsis:             A documentation-generation tool for Haskell libraries  description:          Haddock is a documentation-generation tool for Haskell                        libraries @@ -13,7 +13,7 @@ bug-reports:          https://github.com/haskell/haddock/issues  copyright:            (c) Simon Marlow, David Waern  category:             Documentation  build-type:           Simple -tested-with:          GHC==8.12.*, GHC==8.10.*, GHC==8.8.1 +tested-with:          GHC==9.0.*  extra-source-files:    CHANGES.md @@ -35,8 +35,8 @@ data-files:    html/Ocean.theme/ocean.css    html/Ocean.theme/plus.gif    html/Ocean.theme/synopsis.png -  html/NewOcean.std-theme/new-ocean.css -  html/NewOcean.std-theme/synopsis.png +  html/Linuwial.std-theme/linuwial.css +  html/Linuwial.std-theme/synopsis.png    latex/haddock.sty  library @@ -44,10 +44,9 @@ library    -- this package typically supports only single major versions    build-depends: base            ^>= 4.16.0 -               , Cabal           ^>= 2.4.0                 , ghc             ^>= 9.1                 , ghc-paths       ^>= 0.1.0.9 -               , haddock-library ^>= 1.8.0 +               , haddock-library ^>= 1.9.0                 , xhtml           ^>= 3000.2.2    -- Versions for the dependencies below are transitively pinned by @@ -66,11 +65,16 @@ library    hs-source-dirs: src -  ghc-options: -funbox-strict-fields -Wall -fwarn-tabs -Wincomplete-uni-patterns -Wincomplete-record-updates -O2 +  ghc-options: -funbox-strict-fields -O2 +               -Wall +               -Wcompat +               -Widentities +               -Wredundant-constraints +               -Wnoncanonical-monad-instances +               -Wmissing-home-modules +               -Wincomplete-uni-patterns +               -Wincomplete-record-updates -  ghc-options: -Wall -  if impl(ghc >= 8.0) -    ghc-options: -Wcompat -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances    exposed-modules:      Documentation.Haddock @@ -170,13 +174,12 @@ test-suite spec      Haddock.Backends.Hyperlinker.Parser      Haddock.Backends.Hyperlinker.Types -  build-depends: Cabal           ^>= 2.4 -               , ghc             ^>= 8.9 -               , ghc-paths       ^>= 0.1.0.9 -               , haddock-library ^>= 1.8.0 +  build-depends: ghc             ^>= 9.1 +               , ghc-paths       ^>= 0.1.0.12 +               , haddock-library ^>= 1.9.0                 , xhtml           ^>= 3000.2.2 -               , hspec           >= 2.4.4 && < 2.6 -               , QuickCheck      ^>= 2.11 +               , hspec           >= 2.4.4 && < 2.8 +               , QuickCheck      >= 2.11  && ^>= 2.14    -- Versions for the dependencies below are transitively pinned by    -- the non-reinstallable `ghc` package and hence need no version @@ -192,7 +195,7 @@ test-suite spec                 , transformers    build-tool-depends: -    hspec-discover:hspec-discover >= 2.4.4 && < 2.6 +    hspec-discover:hspec-discover >= 2.4.4 && < 2.8  source-repository head    type:     git diff --git a/haddock-api/resources/html/NewOcean.std-theme/new-ocean.css b/haddock-api/resources/html/Linuwial.std-theme/linuwial.css index 5450ae2e..cbb58a03 100644 --- a/haddock-api/resources/html/NewOcean.std-theme/new-ocean.css +++ b/haddock-api/resources/html/Linuwial.std-theme/linuwial.css @@ -11,7 +11,7 @@ html {  body {    background: #fefefe; -  color: #333; +  color: #111;    text-align: left;    min-height: 100vh;    position: relative; @@ -234,7 +234,7 @@ Display the package name on top of the menu links and center both elements:   */   body, button { -   font: 400 15px/1.4 'PT Sans', +   font: 400 14px/1.4 'PT Sans',       /* Fallback Font Stack */       -apple-system,  	  BlinkMacSystemFont, @@ -390,6 +390,8 @@ pre {    margin: 1em 0 0 0;    background-color: #f7f7f7;    overflow: auto; +  border: 1px solid #ddd; +  border-radius: 0.3em;  }  pre + p { @@ -400,8 +402,15 @@ pre + pre {    margin-top: 0.5em;  } +blockquote { +  border-left: 3px solid #c7a5d3; +  background-color: #eee4f1; +  margin: 0.5em; +  padding: 0.0005em 0.3em 0.5em 0.5em; +} +  .src { -  background: #f4f4f4; +  background: #f2f2f2;    padding: 0.2em 0.5em;  } @@ -461,42 +470,10 @@ table.info {    text-align: right;  } -div#style-menu-holder { -  position: relative; -  z-index: 2; -  display: inline; -} - -#style-menu { -  position: absolute; -  z-index: 1; -  overflow: visible; -  background: #374c5e; -  margin: 0; -  text-align: center; -  right: 0; -  padding: 0; -  top: 1.25em; -} -  #style-menu li { -	display: inline-block; +	display: block;  	border-style: none; -	margin: 0; -	padding: 0; -	color: #000;  	list-style-type: none; -	border-top: 1px solid #919191 -} - -#style-menu li + li { -	border-left: 1px solid #919191; -} - -#style-menu a { -  width: 6em; -  padding: 3px; -  display: block;  }  #footer { @@ -526,7 +503,7 @@ div#style-menu-holder {  }  #contents-list { -  background:  #f7f7f7; +  background: #f4f4f4;    padding: 1em;    margin: 0;  } @@ -889,3 +866,12 @@ div#style-menu-holder {  }  /* @end */ + +/* @group Dropdown menus */ + +#preferences-menu, #style-menu { +  width: 25em; +  overflow-y: auto; +} + +/* @end */ diff --git a/haddock-api/resources/html/NewOcean.std-theme/synopsis.png b/haddock-api/resources/html/Linuwial.std-theme/synopsis.png Binary files differindex 85fb86ec..85fb86ec 100644 --- a/haddock-api/resources/html/NewOcean.std-theme/synopsis.png +++ b/haddock-api/resources/html/Linuwial.std-theme/synopsis.png diff --git a/haddock-api/resources/html/README.md b/haddock-api/resources/html/README.md index 0552f6fd..d555989d 100644 --- a/haddock-api/resources/html/README.md +++ b/haddock-api/resources/html/README.md @@ -13,4 +13,10 @@ After each change to the TypeScript sources, compile and copy the generated file  ```  gulp && cp *.min.js path-to/generated-haddock-docs && cp *.js.map path-to/generated-haddock-docs -```
\ No newline at end of file +``` + +If you are editing the CSS, you'll also need to copy the edited CSS files. E.g. if you are editing the global/default quick-jump.css and the Linuwial theme's CSS, then + +``` +cp quick-jump.css Linuwial.std-theme/linuwial.css path-to/generated-haddock-docs +``` diff --git a/haddock-api/resources/html/haddock-bundle.min.js b/haddock-api/resources/html/haddock-bundle.min.js index 7881dc10..45adda98 100644 --- a/haddock-api/resources/html/haddock-bundle.min.js +++ b/haddock-api/resources/html/haddock-bundle.min.js @@ -1,2 +1,2 @@ -!function i(s,a,l){function c(t,e){if(!a[t]){if(!s[t]){var n="function"==typeof require&&require;if(!e&&n)return n(t,!0);if(u)return u(t,!0);var o=new Error("Cannot find module '"+t+"'");throw o.code="MODULE_NOT_FOUND",o}var r=a[t]={exports:{}};s[t][0].call(r.exports,function(e){return c(s[t][1][e]||e)},r,r.exports,i,s,a,l)}return a[t].exports}for(var u="function"==typeof require&&require,e=0;e<l.length;e++)c(l[e]);return c}({1:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.setCookie=function(e,t){document.cookie=e+"="+encodeURIComponent(t)+";path=/;"},n.clearCookie=function(e){document.cookie=e+"=;path=/;expires=Thu, 01-Jan-1970 00:00:01 GMT;"},n.getCookie=function(e){for(var t=e+"=",n=document.cookie.split(";"),o=0;o<n.length;o++){for(var r=n[o];" "==r.charAt(0);)r=r.substring(1,r.length);if(0==r.indexOf(t))return decodeURIComponent(r.substring(t.length,r.length))}return null}},{}],2:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var i=e("./cookies"),s={},c={};function u(e){var t=s[e];if(null==t)throw new Error("could not find <details> element with id '"+e+"'");return t}function o(e){for(var t,n=e.target,o=n.id,r=u(o),i=r.element.open,s=0,a=r.toggles;s<a.length;s++){var l=a[s];l.classList.contains("details-toggle-control")&&(l.classList.add(i?"collapser":"expander"),l.classList.remove(i?"expander":"collapser"))}n.open==r.openByDefault?delete c[o]:c[o]=!0,t=Object.keys(c),document.cookie="toggled="+encodeURIComponent(t.join("+"))}function r(e){e.preventDefault();var t,n=e.currentTarget.getAttribute("data-details-id");if(!n)throw new Error("element with class 'details-toggle' has no 'data-details-id' attribute!");(t=u(n).element).open=!t.open}n.init=function(){!function(){for(var e=0,t=Array.prototype.slice.call(document.getElementsByTagName("details"));e<t.length;e++){var n=t[e];"string"==typeof n.id&&0<n.id.length&&(s[n.id]={element:n,openByDefault:!!n.open,toggles:[]},n.addEventListener("toggle",o))}}(),function(){var e=i.getCookie("toggled");if(e)for(var t=0,n=e.split("+");t<n.length;t++){var o=n[t],r=s[o];c[o]=!0,r&&(r.element.open=!r.element.open)}}(),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=u(t);n.toggles.push(e),e.addEventListener("click",r),e.classList.contains("details-toggle-control")&&e.classList.add(n.element.open?"collapser":"expander")})}},{"./cookies":1}],3:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var o,r=e("./style-menu"),i=e("./details-helper"),s=e("./quick-jump");o=function(){document.body.classList.add("js-enabled"),r.init(),i.init(),s.init()},"interactive"===document.readyState?o():document.addEventListener("readystatechange",function(){"interactive"===document.readyState&&o()})},{"./details-helper":2,"./quick-jump":4,"./style-menu":5}],4:[function(e,t,n){"use strict";var o,r=this&&this.__extends||(o=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},function(e,t){function n(){this.constructor=e}o(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)});Object.defineProperty(n,"__esModule",{value:!0});var i=e("fuse.js"),s=e("preact"),a=s.h,l=s.Component;var c=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return r(t,e),t.prototype.render=function(t){return a("li",null,a("a",{href:"#",onClick:function(e){e.preventDefault(),t.onClick()}},t.title))},t}(l);function u(e){var t=document.querySelector("#page-menu"),n=document.createElement("li");t.insertBefore(n,t.firstChild),s.render(a(c,{onClick:e,title:"Quick Jump"}),t,n)}function h(e,t){return t.length<=e?t:t.slice(0,e)}var d=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.linkIndex=0,e.focusPlease=!1,e.navigatedByKeyboard=!1,e}return r(e,t),e.prototype.componentWillMount=function(){var e,t,n,o,r=this;this.setState({searchString:"",isVisible:!1,expanded:{},activeLinkIndex:-1,moduleResults:[]}),e=this.props.baseUrl+"/doc-index.json",t=function(e){r.setState({fuse:new i(e,{threshold:.25,caseSensitive:!0,includeScore:!0,tokenize:!0,keys:[{name:"name",weight:.7},{name:"module",weight:.3}]}),moduleResults:[]})},n=function(e){console&&console.error("could not load 'doc-index.json' for searching",e),r.setState({failedLoading:!0})},(o=new XMLHttpRequest).onreadystatechange=function(){if(o.readyState===XMLHttpRequest.DONE)if(200===o.status){if(t)try{t(JSON.parse(o.responseText))}catch(e){n(o)}}else n&&n(o)},o.open("GET",e,!0),o.send(),document.addEventListener("mousedown",this.hide.bind(this)),document.addEventListener("keydown",function(e){r.state.isVisible&&("Escape"===e.key?r.hide():"ArrowUp"===e.key||"k"===e.key&&e.ctrlKey?(e.preventDefault(),r.navigateLinks(-1)):"ArrowDown"===e.key||"j"===e.key&&e.ctrlKey?(e.preventDefault(),r.navigateLinks(1)):"Enter"===e.key&&0<=r.state.activeLinkIndex&&r.followActiveLink()),"s"===e.key&&"input"!==e.target.tagName.toLowerCase()&&(e.preventDefault(),r.show())})},e.prototype.hide=function(){this.setState({isVisible:!1,searchString:""})},e.prototype.show=function(){this.state.isVisible||(this.focusPlease=!0,this.setState({isVisible:!0,activeLinkIndex:-1}))},e.prototype.toggleVisibility=function(){this.state.isVisible?this.hide():this.show()},e.prototype.navigateLinks=function(e){var t=Math.max(-1,Math.min(this.linkIndex-1,this.state.activeLinkIndex+e));this.navigatedByKeyboard=!0,this.setState({activeLinkIndex:t})},e.prototype.followActiveLink=function(){this.activeLinkAction&&this.activeLinkAction()},e.prototype.updateResults=function(){var e=this.input&&this.input.value||"",t=this.state.fuse.search(e),o={};t.forEach(function(e){var t=e.item.module;(o[t]||(o[t]=[])).push(e)});var r=[],n=function(e){var t=o[e],n=0;t.forEach(function(e){n+=1/e.score}),r.push({module:e,totalScore:1/n,items:t})};for(var i in o)n(i);r.sort(function(e,t){return e.totalScore-t.totalScore}),this.setState({searchString:e,isVisible:!0,moduleResults:r})},e.prototype.componentDidUpdate=function(){if(this.searchResults&&this.activeLink&&this.navigatedByKeyboard){var e=this.activeLink.getClientRects()[0],t=this.searchResults.getClientRects()[0].top;e.bottom>window.innerHeight?this.searchResults.scrollTop+=e.bottom-window.innerHeight+80:e.top<t&&(this.searchResults.scrollTop-=t-e.top+80)}this.focusPlease&&this.input&&this.input.focus(),this.navigatedByKeyboard=!1,this.focusPlease=!1},e.prototype.componentDidMount=function(){this.props.showHideTrigger(this.toggleVisibility.bind(this))},e.prototype.render=function(e,t){var r=this;if(t.failedLoading){var n="file:"==window.location.protocol;return a("div",{id:"search",class:t.isVisible?"":"hidden"},a("div",{id:"search-results"},a("p",{class:"error"},"Failed to load file 'doc-index.json' containing definitions in this package."),n?a("p",{class:"error"},"To use quick jump, load this page with HTTP (from a local static file web server) instead of using the ",a("code",null,"file://")," protocol. (For security reasons, it is not possible to fetch auxiliary files using JS in a HTML page opened with ",a("code",null,"file://"),".)"):[]))}this.linkIndex=0;var o=function(e){e.stopPropagation()},i=h(10,t.moduleResults).map(function(e){return r.renderResultsInModule(e)});return a("div",{id:"search",class:t.isVisible?"":"hidden"},a("div",{id:"search-form",onMouseDown:o},a("input",{placeholder:"Search in package by name",ref:function(e){r.input=e},onFocus:this.show.bind(this),onClick:this.show.bind(this),onInput:this.updateResults.bind(this)})),a("div",{id:"search-results",ref:function(e){r.searchResults=e},onMouseDown:o,onMouseOver:function(e){for(var t=e.target;t&&"function"==typeof t.getAttribute;){var n=t.getAttribute("data-link-index");if("string"==typeof n){var o=parseInt(n,10);r.setState({activeLinkIndex:o});break}t=t.parentNode}}},""===t.searchString?[a(v,null),a(f,null)]:0==i.length?a(g,{searchString:t.searchString}):a("ul",null,i)))},e.prototype.renderResultsInModule=function(e){var n=this,t=e.items,o=e.module,r=this.state.expanded[o]||t.length<=10,i=r?t:h(8,t);return a("li",{class:"search-module"},a("h4",null,o),a("ul",null,i.map(function(e){return t=e.item,a("li",{class:"search-result"},n.navigationLink(n.props.baseUrl+"/"+t.link,{},a(p,{html:t.display_html})));var t}),r?[]:a("li",{class:"more-results"},this.actionLink(function(){var e=Object.assign({},n.state.expanded);e[o]=!0,n.setState({expanded:e})},{},"show "+(t.length-i.length)+" more results from this module"))))},e.prototype.navigationLink=function(e,t){for(var n=this,o=[],r=2;r<arguments.length;r++)o[r-2]=arguments[r];var i=Object.assign({href:e,onClick:this.hide.bind(this)},t);return this.menuLink.apply(this,[i,function(){window.location.href=e,n.hide()}].concat(o))},e.prototype.actionLink=function(t,e){for(var n=[],o=2;o<arguments.length;o++)n[o-2]=arguments[o];var r=Object.assign({href:"#",onClick:function(e){e.preventDefault(),t()}},e);return this.menuLink.apply(this,[r,t].concat(n))},e.prototype.menuLink=function(e,t){for(var n=this,o=[],r=2;r<arguments.length;r++)o[r-2]=arguments[r];var i=this.linkIndex;i===this.state.activeLinkIndex&&(e.class=(e.class?e.class+" ":"")+"active-link",e.ref=function(e){e&&(n.activeLink=e)},this.activeLinkAction=t);var s=Object.assign({"data-link-index":i},e);return this.linkIndex+=1,a.apply(void 0,["a",s].concat(o))},e}(l),p=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return r(t,e),t.prototype.shouldComponentUpdate=function(e){return this.props.html!==e.html},t.prototype.render=function(e){return a("div",{dangerouslySetInnerHTML:{__html:e.html}})},t}(l);function f(){return a("table",{class:"keyboard-shortcuts"},a("tr",null,a("th",null,"Key"),a("th",null,"Shortcut")),a("tr",null,a("td",null,a("span",{class:"key"},"s")),a("td",null,"Open this search box")),a("tr",null,a("td",null,a("span",{class:"key"},"esc")),a("td",null,"Close this search box")),a("tr",null,a("td",null,a("span",{class:"key"},"↓"),",",a("span",{class:"key"},"ctrl")," + ",a("span",{class:"key"},"j")),a("td",null,"Move down in search results")),a("tr",null,a("td",null,a("span",{class:"key"},"↑"),",",a("span",{class:"key"},"ctrl")," + ",a("span",{class:"key"},"k")),a("td",null,"Move up in search results")),a("tr",null,a("td",null,a("span",{class:"key"},"↵")),a("td",null,"Go to active search result")))}function v(){return a("p",null,"You can find any exported type, constructor, class, function or pattern defined in this package by (approximate) name.")}function g(e){var t=[a("p",null,"Your search for '",e.searchString,"' produced the following list of results: ",a("code",null,"[]"),"."),a("p",null,a("code",null,"Nothing")," matches your query for '",e.searchString,"'."),a("p",null,a("code",null,"Left \"no matches for '",e.searchString,"'\" :: Either String (NonEmpty SearchResult)"))];return t[(e.searchString||"a").charCodeAt(0)%t.length]}function m(e,t){s.render(a(d,{baseUrl:e||".",showHideTrigger:t||u}),document.body)}n.init=m,window.quickNav={init:m}},{"fuse.js":6,preact:7}],5:[function(e,t,n){"use strict";var o,r=this&&this.__extends||(o=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},function(e,t){function n(){this.constructor=e}o(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)});Object.defineProperty(n,"__esModule",{value:!0});var i=e("./cookies"),s=e("preact"),a=s.h,l=s.Component,c=/\s\s+/g,u=/^\s+|\s+$/g;function h(e){return(" "+e+" ").replace(c," ")}function d(e){return e.replace(u,"")}function p(e,t){var n=h(e.className||"");n.indexOf(" "+t+" ")<0&&(e.className=d(n+" "+t))}function f(e,t){var n=h(e.className||"");n=n.replace(" "+t+" "," "),e.className=d(n)}function v(e,t,n,o){var r;return null==o&&(r=t,o=!(0<=h(e.className||"").indexOf(" "+r+" "))),o?(f(e,n),p(e,t)):(f(e,t),p(e,n)),o}var g,m,y=(g="show",m="hide",function(e,t){return v(e,g,m,t)});function _(){return Array.prototype.slice.call(document.getElementsByTagName("link")).filter(function(e){return-1!=e.rel.indexOf("style")&&e.title})}var k=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return r(t,e),t.prototype.render=function(e){return a("li",null,a("div",{id:"style-menu-holder",onClick:function(){var e,t;return(t=document.getElementById("style-menu"))&&y(t,e),!1}},a("a",{href:"#"},"Style ▾"),a("ul",{id:"style-menu",class:"hide"},e.stys.map(function(e){return a("li",null,a("a",{href:"#",onClick:function(){return b(e),!1}},e))}))))},t}(l);function b(e){for(var t=_(),n=null,o=0;o<t.length;o++){var r=t[o];r.disabled=!0,r.title==e&&(n=r)}n?(n.disabled=!1,i.setCookie("haddock-style",e)):(t[0].disabled=!1,i.clearCookie("haddock-style"))}n.init=function(){var e;!function(){var e=_().map(function(e){return e.title});if(1<e.length){var t=document.querySelector("#page-menu"),n=document.createElement("li");t.appendChild(n),s.render(a(k,{stys:e,title:"Style"}),t,n)}}(),(e=i.getCookie("haddock-style"))&&b(e)}},{"./cookies":1,preact:7}],6:[function(e,t,n){var o,r;o=this,r=function(){return function(n){var o={};function r(e){if(o[e])return o[e].exports;var t=o[e]={i:e,l:!1,exports:{}};return n[e].call(t.exports,t,t.exports,r),t.l=!0,t.exports}return r.m=n,r.c=o,r.i=function(e){return e},r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:n})},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=8)}([function(e,t,n){"use strict";e.exports=function(e){return Array.isArray?Array.isArray(e):"[object Array]"===Object.prototype.toString.call(e)}},function(e,t,n){"use strict";var o=function(){function o(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(e,t,n){return t&&o(e.prototype,t),n&&o(e,n),e}}();var u=n(5),h=n(7),_=n(4),r=function(){function y(e,t){var n=t.location,o=void 0===n?0:n,r=t.distance,i=void 0===r?100:r,s=t.threshold,a=void 0===s?.6:s,l=t.maxPatternLength,c=void 0===l?32:l,u=t.isCaseSensitive,h=void 0!==u&&u,d=t.tokenSeparator,p=void 0===d?/ +/g:d,f=t.findAllMatches,v=void 0!==f&&f,g=t.minMatchCharLength,m=void 0===g?1:g;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,y),this.options={location:o,distance:i,threshold:a,maxPatternLength:c,isCaseSensitive:h,tokenSeparator:p,findAllMatches:v,minMatchCharLength:m},this.pattern=this.options.isCaseSensitive?e:e.toLowerCase(),this.pattern.length<=c&&(this.patternAlphabet=_(this.pattern))}return o(y,[{key:"search",value:function(e){if(this.options.isCaseSensitive||(e=e.toLowerCase()),this.pattern===e)return{isMatch:!0,score:0,matchedIndices:[[0,e.length-1]]};var t=this.options,n=t.maxPatternLength,o=t.tokenSeparator;if(this.pattern.length>n)return u(e,this.pattern,o);var r=this.options,i=r.location,s=r.distance,a=r.threshold,l=r.findAllMatches,c=r.minMatchCharLength;return h(e,this.pattern,this.patternAlphabet,{location:i,distance:s,threshold:a,findAllMatches:l,minMatchCharLength:c})}}]),y}();e.exports=r},function(e,t,n){"use strict";var u=n(0);e.exports=function(e,t){return function e(t,n,o){if(n){var r=n.indexOf("."),i=n,s=null;-1!==r&&(i=n.slice(0,r),s=n.slice(r+1));var a=t[i];if(null!=a)if(s||"string"!=typeof a&&"number"!=typeof a)if(u(a))for(var l=0,c=a.length;l<c;l+=1)e(a[l],s,o);else s&&e(a,s,o);else o.push(a.toString())}else o.push(t);return o}(e,t,[])}},function(e,t,n){"use strict";e.exports=function(){for(var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:[],t=1<arguments.length&&void 0!==arguments[1]?arguments[1]:1,n=[],o=-1,r=-1,i=0,s=e.length;i<s;i+=1){var a=e[i];a&&-1===o?o=i:a||-1===o||(t<=(r=i-1)-o+1&&n.push([o,r]),o=-1)}return e[i-1]&&t<=i-o&&n.push([o,i-1]),n}},function(e,t,n){"use strict";e.exports=function(e){for(var t={},n=e.length,o=0;o<n;o+=1)t[e.charAt(o)]=0;for(var r=0;r<n;r+=1)t[e.charAt(r)]|=1<<n-r-1;return t}},function(e,t,n){"use strict";var u=/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g;e.exports=function(e,t){var n=2<arguments.length&&void 0!==arguments[2]?arguments[2]:/ +/g,o=new RegExp(t.replace(u,"\\$&").replace(n,"|")),r=e.match(o),i=!!r,s=[];if(i)for(var a=0,l=r.length;a<l;a+=1){var c=r[a];s.push([e.indexOf(c),c.length-1])}return{score:i?.5:1,isMatch:i,matchedIndices:s}}},function(e,t,n){"use strict";e.exports=function(e,t){var n=t.errors,o=void 0===n?0:n,r=t.currentLocation,i=void 0===r?0:r,s=t.expectedLocation,a=void 0===s?0:s,l=t.distance,c=void 0===l?100:l,u=o/e.length,h=Math.abs(a-i);return c?u+h/c:h?1:u}},function(e,t,n){"use strict";var U=n(6),R=n(3);e.exports=function(e,t,n,o){for(var r=o.location,i=void 0===r?0:r,s=o.distance,a=void 0===s?100:s,l=o.threshold,c=void 0===l?.6:l,u=o.findAllMatches,h=void 0!==u&&u,d=o.minMatchCharLength,p=void 0===d?1:d,f=i,v=e.length,g=c,m=e.indexOf(t,f),y=t.length,_=[],k=0;k<v;k+=1)_[k]=0;if(-1!==m){var b=U(t,{errors:0,currentLocation:m,expectedLocation:f,distance:a});if(g=Math.min(b,g),-1!==(m=e.lastIndexOf(t,f+y))){var x=U(t,{errors:0,currentLocation:m,expectedLocation:f,distance:a});g=Math.min(x,g)}}m=-1;for(var w=[],S=1,L=y+v,C=1<<y-1,M=0;M<y;M+=1){for(var N=0,A=L;N<A;){U(t,{errors:M,currentLocation:f+A,expectedLocation:f,distance:a})<=g?N=A:L=A,A=Math.floor((L-N)/2+N)}L=A;var O=Math.max(1,f-A+1),I=h?v:Math.min(f+A,v)+y,j=Array(I+2);j[I+1]=(1<<M)-1;for(var E=I;O<=E;E-=1){var T=E-1,P=n[e.charAt(T)];if(P&&(_[T]=1),j[E]=(j[E+1]<<1|1)&P,0!==M&&(j[E]|=(w[E+1]|w[E])<<1|1|w[E+1]),j[E]&C&&(S=U(t,{errors:M,currentLocation:T,expectedLocation:f,distance:a}))<=g){if(g=S,(m=T)<=f)break;O=Math.max(1,2*f-m)}}if(g<U(t,{errors:M+1,currentLocation:f,expectedLocation:f,distance:a}))break;w=j}return{isMatch:0<=m,score:0===S?.001:S,matchedIndices:R(_,p)}}},function(e,t,n){"use strict";var o=function(){function o(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(e,t,n){return t&&o(e.prototype,t),n&&o(e,n),e}}();var i=n(1),F=n(2),U=n(0),r=function(){function D(e,t){var n=t.location,o=void 0===n?0:n,r=t.distance,i=void 0===r?100:r,s=t.threshold,a=void 0===s?.6:s,l=t.maxPatternLength,c=void 0===l?32:l,u=t.caseSensitive,h=void 0!==u&&u,d=t.tokenSeparator,p=void 0===d?/ +/g:d,f=t.findAllMatches,v=void 0!==f&&f,g=t.minMatchCharLength,m=void 0===g?1:g,y=t.id,_=void 0===y?null:y,k=t.keys,b=void 0===k?[]:k,x=t.shouldSort,w=void 0===x||x,S=t.getFn,L=void 0===S?F:S,C=t.sortFn,M=void 0===C?function(e,t){return e.score-t.score}:C,N=t.tokenize,A=void 0!==N&&N,O=t.matchAllTokens,I=void 0!==O&&O,j=t.includeMatches,E=void 0!==j&&j,T=t.includeScore,P=void 0!==T&&T,U=t.verbose,R=void 0!==U&&U;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,D),this.options={location:o,distance:i,threshold:a,maxPatternLength:c,isCaseSensitive:h,tokenSeparator:p,findAllMatches:v,minMatchCharLength:m,id:_,keys:b,includeMatches:E,includeScore:P,shouldSort:w,getFn:L,sortFn:M,verbose:R,tokenize:A,matchAllTokens:I},this.setCollection(e)}return o(D,[{key:"setCollection",value:function(e){return this.list=e}},{key:"search",value:function(e){this._log('---------\nSearch pattern: "'+e+'"');var t=this._prepareSearchers(e),n=t.tokenSearchers,o=t.fullSearcher,r=this._search(n,o),i=r.weights,s=r.results;return this._computeScore(i,s),this.options.shouldSort&&this._sort(s),this._format(s)}},{key:"_prepareSearchers",value:function(){var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:"",t=[];if(this.options.tokenize)for(var n=e.split(this.options.tokenSeparator),o=0,r=n.length;o<r;o+=1)t.push(new i(n[o],this.options));return{tokenSearchers:t,fullSearcher:new i(e,this.options)}}},{key:"_search",value:function(){var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:[],t=arguments[1],n=this.list,o={},r=[];if("string"==typeof n[0]){for(var i=0,s=n.length;i<s;i+=1)this._analyze({key:"",value:n[i],record:i,index:i},{resultMap:o,results:r,tokenSearchers:e,fullSearcher:t});return{weights:null,results:r}}for(var a={},l=0,c=n.length;l<c;l+=1)for(var u=n[l],h=0,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||1<p.weight)throw new Error("Key weight has to be > 0 and <= 1");p=p.name}else a[p]={weight:1};this._analyze({key:p,value:this.options.getFn(u,p),record:u,index:l},{resultMap:o,results:r,tokenSearchers:e,fullSearcher:t})}return{weights:a,results:r}}},{key:"_analyze",value:function(e,t){var n=e.key,o=e.arrayIndex,r=void 0===o?-1:o,i=e.value,s=e.record,a=e.index,l=t.tokenSearchers,c=void 0===l?[]:l,u=t.fullSearcher,h=void 0===u?[]:u,d=t.resultMap,p=void 0===d?{}:d,f=t.results,v=void 0===f?[]:f;if(null!=i){var g=!1,m=-1,y=0;if("string"==typeof i){this._log("\nKey: "+(""===n?"-":n));var _=h.search(i);if(this._log('Full text: "'+i+'", score: '+_.score),this.options.tokenize){for(var k=i.split(this.options.tokenSeparator),b=[],x=0;x<c.length;x+=1){var w=c[x];this._log('\nPattern: "'+w.pattern+'"');for(var S=!1,L=0;L<k.length;L+=1){var C=k[L],M=w.search(C),N={};M.isMatch?(N[C]=M.score,S=g=!0,b.push(M.score)):(N[C]=1,this.options.matchAllTokens||b.push(1)),this._log('Token: "'+C+'", score: '+N[C])}S&&(y+=1)}m=b[0];for(var A=b.length,O=1;O<A;O+=1)m+=b[O];m/=A,this._log("Token score average:",m)}var I=_.score;-1<m&&(I=(I+m)/2),this._log("Score average:",I);var j=!this.options.tokenize||!this.options.matchAllTokens||y>=c.length;if(this._log("\nCheck Matches: "+j),(g||_.isMatch)&&j){var E=p[a];E?E.output.push({key:n,arrayIndex:r,value:i,score:I,matchedIndices:_.matchedIndices}):(p[a]={item:s,output:[{key:n,arrayIndex:r,value:i,score:I,matchedIndices:_.matchedIndices}]},v.push(p[a]))}}else if(U(i))for(var T=0,P=i.length;T<P;T+=1)this._analyze({key:n,arrayIndex:T,value:i[T],record:s,index:a},{resultMap:p,results:v,tokenSearchers:c,fullSearcher:h})}}},{key:"_computeScore",value:function(e,t){this._log("\n\nComputing score:\n");for(var n=0,o=t.length;n<o;n+=1){for(var r=t[n].output,i=r.length,s=1,a=1,l=0;l<i;l+=1){var c=e?e[r[l].key].weight:1,u=(1===c?r[l].score:r[l].score||.001)*c;1!==c?a=Math.min(a,u):s*=r[l].nScore=u}t[n].score=1===a?s:a,this._log(t[n])}}},{key:"_sort",value:function(e){this._log("\n\nSorting...."),e.sort(this.options.sortFn)}},{key:"_format",value:function(e){var t=[];this.options.verbose&&this._log("\n\nOutput:\n\n",JSON.stringify(e));var n=[];this.options.includeMatches&&n.push(function(e,t){var n=e.output;t.matches=[];for(var o=0,r=n.length;o<r;o+=1){var i=n[o];if(0!==i.matchedIndices.length){var s={indices:i.matchedIndices,value:i.value};i.key&&(s.key=i.key),i.hasOwnProperty("arrayIndex")&&-1<i.arrayIndex&&(s.arrayIndex=i.arrayIndex),t.matches.push(s)}}}),this.options.includeScore&&n.push(function(e,t){t.score=e.score});for(var o=0,r=e.length;o<r;o+=1){var i=e[o];if(this.options.id&&(i.item=this.options.getFn(i.item,this.options.id)[0]),n.length){for(var s={item:i.item},a=0,l=n.length;a<l;a+=1)n[a](i,s);t.push(s)}else t.push(i.item)}return t}},{key:"_log",value:function(){var e;this.options.verbose&&(e=console).log.apply(e,arguments)}}]),D}();e.exports=r}])},"object"==typeof n&&"object"==typeof t?t.exports=r():"function"==typeof define&&define.amd?define("Fuse",[],r):"object"==typeof n?n.Fuse=r():o.Fuse=r()},{}],7:[function(e,y,t){!function(){"use strict";function n(e,t){var n,o,r,i,s=h;for(i=arguments.length;2<i--;)u.push(arguments[i]);for(t&&null!=t.children&&(u.length||u.push(t.children),delete t.children);u.length;)if((o=u.pop())&&void 0!==o.pop)for(i=o.length;i--;)u.push(o[i]);else"boolean"==typeof o&&(o=null),(r="function"!=typeof e)&&(null==o?o="":"number"==typeof o?o=String(o):"string"!=typeof o&&(r=!1)),r&&n?s[s.length-1]+=o:s===h?s=[o]:s.push(o),n=r;var a=new c;return a.nodeName=e,a.children=s,a.attributes=null==t?void 0:t,a.key=null==t?void 0:t.key,void 0!==R.vnode&&R.vnode(a),a}function C(e,t){for(var n in t)e[n]=t[n];return e}function i(e){!e.__d&&(e.__d=!0)&&1==p.push(e)&&(R.debounceRendering||r)(t)}function t(){var e,t=p;for(p=[];e=t.pop();)e.__d&&P(e)}function L(e,t){return e.__n===t||e.nodeName.toLowerCase()===t.toLowerCase()}function M(e){var t=C({},e.attributes);t.children=e.children;var n=e.nodeName.defaultProps;if(void 0!==n)for(var o in n)void 0===t[o]&&(t[o]=n[o]);return t}function N(e){var t=e.parentNode;t&&t.removeChild(e)}function v(e,t,n,o,r){if("className"===t&&(t="class"),"key"===t);else if("ref"===t)n&&n(null),o&&o(e);else if("class"!==t||r)if("style"===t){if(o&&"string"!=typeof o&&"string"!=typeof n||(e.style.cssText=o||""),o&&"object"==typeof o){if("string"!=typeof n)for(var i in n)i in o||(e.style[i]="");for(var i in o)e.style[i]="number"==typeof o[i]&&!1===d.test(i)?o[i]+"px":o[i]}}else if("dangerouslySetInnerHTML"===t)o&&(e.innerHTML=o.__html||"");else if("o"==t[0]&&"n"==t[1]){var s=t!==(t=t.replace(/Capture$/,""));t=t.toLowerCase().substring(2),o?n||e.addEventListener(t,l,s):e.removeEventListener(t,l,s),(e.__l||(e.__l={}))[t]=o}else if("list"!==t&&"type"!==t&&!r&&t in e){try{e[t]=null==o?"":o}catch(e){}null!=o&&!1!==o||"spellcheck"==t||e.removeAttribute(t)}else{var a=r&&t!==(t=t.replace(/^xlink:?/,""));null==o||!1===o?a?e.removeAttributeNS("http://www.w3.org/1999/xlink",t.toLowerCase()):e.removeAttribute(t):"function"!=typeof o&&(a?e.setAttributeNS("http://www.w3.org/1999/xlink",t.toLowerCase(),o):e.setAttribute(t,o))}else e.className=o||""}function l(e){return this.__l[e.type](R.event&&R.event(e)||e)}function A(){for(var e;e=D.pop();)R.afterMount&&R.afterMount(e),e.componentDidMount&&e.componentDidMount()}function O(e,t,n,o,r,i){F++||(g=null!=r&&void 0!==r.ownerSVGElement,m=null!=e&&!("__preactattr_"in e));var s=I(e,t,n,o,i);return r&&s.parentNode!==r&&r.appendChild(s),--F||(m=!1,i||A()),s}function I(e,t,n,o,r){var i=e,s=g;if(null!=t&&"boolean"!=typeof t||(t=""),"string"==typeof t||"number"==typeof t)return e&&void 0!==e.splitText&&e.parentNode&&(!e._component||r)?e.nodeValue!=t&&(e.nodeValue=t):(i=document.createTextNode(t),e&&(e.parentNode&&e.parentNode.replaceChild(i,e),j(e,!0))),i.__preactattr_=!0,i;var a,l,c=t.nodeName;if("function"==typeof c)return function(e,t,n,o){var r=e&&e._component,i=r,s=e,a=r&&e._componentConstructor===t.nodeName,l=a,c=M(t);for(;r&&!l&&(r=r.__u);)l=r.constructor===t.nodeName;r&&l&&(!o||r._component)?(T(r,c,3,n,o),e=r.base):(i&&!a&&(U(i),e=s=null),r=E(t.nodeName,c,n),e&&!r.__b&&(r.__b=e,s=null),T(r,c,1,n,o),e=r.base,s&&e!==s&&(s._component=null,j(s,!1)));return e}(e,t,n,o);if(g="svg"===c||"foreignObject"!==c&&g,c=String(c),(!e||!L(e,c))&&(a=c,(l=g?document.createElementNS("http://www.w3.org/2000/svg",a):document.createElement(a)).__n=a,i=l,e)){for(;e.firstChild;)i.appendChild(e.firstChild);e.parentNode&&e.parentNode.replaceChild(i,e),j(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!m&&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)&&function(e,t,n,o,r){var i,s,a,l,c,u=e.childNodes,h=[],d={},p=0,f=0,v=u.length,g=0,m=t?t.length:0;if(0!==v)for(var y=0;y<v;y++){var _=u[y],k=_.__preactattr_,b=m&&k?_._component?_._component.__k:k.key:null;null!=b?(p++,d[b]=_):(k||(void 0!==_.splitText?!r||_.nodeValue.trim():r))&&(h[g++]=_)}if(0!==m)for(var y=0;y<m;y++){l=t[y],c=null;var b=l.key;if(null!=b)p&&void 0!==d[b]&&(c=d[b],d[b]=void 0,p--);else if(f<g)for(i=f;i<g;i++)if(void 0!==h[i]&&(x=s=h[i],S=r,"string"==typeof(w=l)||"number"==typeof w?void 0!==x.splitText:"string"==typeof w.nodeName?!x._componentConstructor&&L(x,w.nodeName):S||x._componentConstructor===w.nodeName)){c=s,h[i]=void 0,i===g-1&&g--,i===f&&f++;break}c=I(c,l,n,o),a=u[y],c&&c!==e&&c!==a&&(null==a?e.appendChild(c):c===a.nextSibling?N(a):e.insertBefore(c,a))}var x,w,S;if(p)for(var y in d)void 0!==d[y]&&j(d[y],!1);for(;f<=g;)void 0!==(c=h[g--])&&j(c,!1)}(i,d,n,o,m||null!=h.dangerouslySetInnerHTML),function(e,t,n){var o;for(o in n)t&&null!=t[o]||null==n[o]||v(e,o,n[o],n[o]=void 0,g);for(o in t)"children"===o||"innerHTML"===o||o in n&&t[o]===("value"===o||"checked"===o?e[o]:n[o])||v(e,o,n[o],n[o]=t[o],g)}(i,t.attributes,h),g=s,i}function j(e,t){var n=e._component;n?U(n):(null!=e.__preactattr_&&e.__preactattr_.ref&&e.__preactattr_.ref(null),!1!==t&&null!=e.__preactattr_||N(e),o(e))}function o(e){for(e=e.lastChild;e;){var t=e.previousSibling;j(e,!0),e=t}}function E(e,t,n){var o,r=f.length;for(e.prototype&&e.prototype.render?(o=new e(t,n),a.call(o,t,n)):((o=new a(t,n)).constructor=e,o.render=s);r--;)if(f[r].constructor===e)return o.__b=f[r].__b,f.splice(r,1),o;return o}function s(e,t,n){return this.constructor(e,n)}function T(e,t,n,o,r){e.__x||(e.__x=!0,e.__r=t.ref,e.__k=t.key,delete t.ref,delete t.key,void 0===e.constructor.getDerivedStateFromProps&&(!e.base||r?e.componentWillMount&&e.componentWillMount():e.componentWillReceiveProps&&e.componentWillReceiveProps(t,o)),o&&o!==e.context&&(e.__c||(e.__c=e.context),e.context=o),e.__p||(e.__p=e.props),e.props=t,e.__x=!1,0!==n&&(1!==n&&!1===R.syncComponentUpdates&&e.base?i(e):P(e,1,r)),e.__r&&e.__r(e))}function P(e,t,n,o){if(!e.__x){var r,i,s,a=e.props,l=e.state,c=e.context,u=e.__p||a,h=e.__s||l,d=e.__c||c,p=e.base,f=e.__b,v=p||f,g=e._component,m=!1,y=d;if(e.constructor.getDerivedStateFromProps&&(l=C(C({},l),e.constructor.getDerivedStateFromProps(a,l)),e.state=l),p&&(e.props=u,e.state=h,e.context=d,2!==t&&e.shouldComponentUpdate&&!1===e.shouldComponentUpdate(a,l,c)?m=!0:e.componentWillUpdate&&e.componentWillUpdate(a,l,c),e.props=a,e.state=l,e.context=c),e.__p=e.__s=e.__c=e.__b=null,e.__d=!1,!m){r=e.render(a,l,c),e.getChildContext&&(c=C(C({},c),e.getChildContext())),p&&e.getSnapshotBeforeUpdate&&(y=e.getSnapshotBeforeUpdate(u,h));var _,k,b=r&&r.nodeName;if("function"==typeof b){var x=M(r);(i=g)&&i.constructor===b&&x.key==i.__k?T(i,x,1,c,!1):(_=i,e._component=i=E(b,x,c),i.__b=i.__b||f,i.__u=e,T(i,x,0,c,!1),P(i,1,n,!0)),k=i.base}else s=v,(_=g)&&(s=e._component=null),(v||1===t)&&(s&&(s._component=null),k=O(s,r,c,n||!p,v&&v.parentNode,!0));if(v&&k!==v&&i!==g){var w=v.parentNode;w&&k!==w&&(w.replaceChild(k,v),_||(v._component=null,j(v,!1)))}if(_&&U(_),(e.base=k)&&!o){for(var S=e,L=e;L=L.__u;)(S=L).base=k;k._component=S,k._componentConstructor=S.constructor}}for(!p||n?D.unshift(e):m||(e.componentDidUpdate&&e.componentDidUpdate(u,h,y),R.afterUpdate&&R.afterUpdate(e));e.__h.length;)e.__h.pop().call(e);F||o||A()}}function U(e){R.beforeUnmount&&R.beforeUnmount(e);var t=e.base;e.__x=!0,e.componentWillUnmount&&e.componentWillUnmount(),e.base=null;var n=e._component;n?U(n):t&&(t.__preactattr_&&t.__preactattr_.ref&&t.__preactattr_.ref(null),N(e.__b=t),f.push(e),o(t)),e.__r&&e.__r(null)}function a(e,t){this.__d=!0,this.context=t,this.props=e,this.state=this.state||{},this.__h=[]}var c=function(){},R={},u=[],h=[],r="function"==typeof Promise?Promise.resolve().then.bind(Promise.resolve()):setTimeout,d=/acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i,p=[],D=[],F=0,g=!1,m=!1,f=[];C(a.prototype,{setState:function(e,t){this.__s||(this.__s=this.state),this.state=C(C({},this.state),"function"==typeof e?e(this.state,this.props):e),t&&this.__h.push(t),i(this)},forceUpdate:function(e){e&&this.__h.push(e),P(this,2)},render:function(){}});var e={h:n,createElement:n,cloneElement:function(e,t){return n(e.nodeName,C(C({},e.attributes),t),2<arguments.length?[].slice.call(arguments,2):e.children)},Component:a,render:function(e,t,n){return O(n,e,{},!1,t,!1)},rerender:t,options:R};void 0!==y?y.exports=e:self.preact=e}()},{}]},{},[3]); +!function i(s,a,l){function c(t,e){if(!a[t]){if(!s[t]){var n="function"==typeof require&&require;if(!e&&n)return n(t,!0);if(u)return u(t,!0);var o=new Error("Cannot find module '"+t+"'");throw o.code="MODULE_NOT_FOUND",o}var r=a[t]={exports:{}};s[t][0].call(r.exports,function(e){return c(s[t][1][e]||e)},r,r.exports,i,s,a,l)}return a[t].exports}for(var u="function"==typeof require&&require,e=0;e<l.length;e++)c(l[e]);return c}({1:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.setCookie=function(e,t){document.cookie=e+"="+encodeURIComponent(t)+";path=/;"},n.clearCookie=function(e){document.cookie=e+"=;path=/;expires=Thu, 01-Jan-1970 00:00:01 GMT;"},n.getCookie=function(e){for(var t=e+"=",n=document.cookie.split(";"),o=0;o<n.length;o++){for(var r=n[o];" "==r.charAt(0);)r=r.substring(1,r.length);if(0==r.indexOf(t))return decodeURIComponent(r.substring(t.length,r.length))}return null}},{}],2:[function(e,t,n){"use strict";var o,r=this&&this.__extends||(o=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},function(e,t){function n(){this.constructor=e}o(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)});Object.defineProperty(n,"__esModule",{value:!0});var i,s,a=e("preact"),l=a.h,c=a.Component;(s=i||(i={}))[s.Closed=0]="Closed",s[s.Open=1]="Open";var u={defaultInstanceState:i.Open,rememberToggles:!0},d=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return r(t,e),t.prototype.render=function(t){return l("li",null,l("a",{href:"#",onClick:function(e){e.preventDefault(),t.onClick()}},t.title))},t}(c);function h(e){var t=document.querySelector("#page-menu"),n=document.createElement("li");t.insertBefore(n,t.firstChild),a.render(l(d,{onClick:e,title:"Instances"}),t,n)}var p=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return r(t,e),t.prototype.componentWillMount=function(){var t=this;document.addEventListener("mousedown",this.hide.bind(this)),document.addEventListener("keydown",function(e){t.state.isVisible&&"Escape"===e.key&&t.hide()})},t.prototype.hide=function(){this.setState({isVisible:!1})},t.prototype.show=function(){this.state.isVisible||this.setState({isVisible:!0})},t.prototype.toggleVisibility=function(){this.state.isVisible?this.hide():this.show()},t.prototype.componentDidMount=function(){this.props.showHideTrigger(this.toggleVisibility.bind(this))},t.prototype.render=function(e,t){return l("div",{id:"preferences",class:t.isVisible?"":"hidden"},l("div",{id:"preferences-menu",class:"dropdown-menu",onMouseDown:function(e){e.stopPropagation()}},l(b,null)))},t}(c);function f(){var e=JSON.stringify(u);try{localStorage.setItem("global",e)}catch(e){}}var v=!1;function g(){if(!v){v=!0;var e=localStorage.getItem("global");if(e)try{var t=JSON.parse(e);u.defaultInstanceState=t.defaultInstanceState,u.rememberToggles=t.rememberToggles}catch(e){if(!(e instanceof SyntaxError||e instanceof TypeError))throw e;localStorage.removeItem("global")}}}function m(t){return function(e){u.defaultInstanceState=t,A(),f(),E(),O()}}function y(e){var t=e.target.checked;u.rememberToggles=t,f(),E(),O()}function _(e){var t=document.getElementById("default-collapse-instances");null!==t&&(t.checked?m(i.Closed)(e):m(i.Open)(e))}function b(){return g(),l("div",null,l("div",null,l("button",{type:"button",onClick:j},"Expand All Instances"),l("button",{type:"button",onClick:P},"Collapse All Instances")),l("div",null,l("input",{type:"checkbox",id:"default-collapse-instances",name:"default-instance-state",checked:u.defaultInstanceState===i.Closed,onClick:_}),l("span",null,"Collapse All Instances By Default")),l("div",null,l("input",{type:"checkbox",id:"remember-toggles",name:"remember-toggles",checked:u.rememberToggles,onClick:y}),l("label",{for:"remember-toggles"},"Remember Manually Collapsed/Expanded Instances")))}var k={};function S(e){var t=k[e];if(null==t)throw new Error("could not find <details> element with id '"+e+"'");return t}function x(){return u.defaultInstanceState==i.Open}function w(e){for(var t=S(e.target.id),n=t.element.open,o=0,r=t.toggles;o<r.length;o++){var i=r[o];i.classList.contains("details-toggle-control")&&(i.classList.add(n?"collapser":"expander"),i.classList.remove(n?"expander":"collapser"))}}function C(e){var t=e.getAttribute("data-details-id");if(!t)throw new Error("element with class "+e+" has no 'data-details-id' attribute!");return t}function L(e){var t=S(C(e)).element;t.open=!t.open}var M="local-details-config:";function I(){return M+document.location.pathname}function E(){for(var e=[],t=0;t<localStorage.length;++t){var n=localStorage.key(t);null!==n&&n.startsWith(M)&&e.push(n)}e.forEach(function(e){localStorage.removeItem(e)})}function O(){if(u.rememberToggles){var e=Array.prototype.slice.call(document.getElementsByClassName("instances details-toggle details-toggle-control")),n=[];e.forEach(function(e){var t=C(e);document.getElementById(t).open!=x()&&n.push(t)});var t=JSON.stringify(n);try{localStorage.setItem(I(),t)}catch(e){}}}function A(){switch(u.defaultInstanceState){case i.Closed:N(!0);break;case i.Open:N(!1)}}function T(e){e.preventDefault(),L(e.currentTarget),O()}function N(o){var e=document.getElementsByClassName("subs instances");[].forEach.call(e,function(e){var t=o?"collapser":"expander",n=e.getElementsByClassName("instances "+t)[0];n&&L(n)})}function P(){N(!0),O()}function j(){N(!1),O()}n.init=function(e){!function(){for(var e=0,t=Array.prototype.slice.call(document.getElementsByTagName("details"));e<t.length;e++){var n=t[e];"string"==typeof n.id&&0<n.id.length&&(k[n.id]={element:n,toggles:[]},n.addEventListener("toggle",w))}}(),Array.prototype.slice.call(document.getElementsByClassName("details-toggle")).forEach(function(e){var t=S(C(e));t.toggles.push(e),e.addEventListener("click",T),e.classList.contains("details-toggle-control")&&e.classList.add(t.element.open?"collapser":"expander")}),function(){if(g(),A(),u.rememberToggles){var e=localStorage.getItem(I());if(e)try{JSON.parse(e).forEach(function(e){S(e).element.open=!x()})}catch(e){if(!(e instanceof SyntaxError||e instanceof TypeError))throw e;localStorage.removeItem(I())}}}(),a.render(l(p,{showHideTrigger:e||h}),document.body)}},{preact:7}],3:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var o,r=e("./style-menu"),i=e("./details-helper"),s=e("./quick-jump");o=function(){document.body.classList.add("js-enabled"),r.init(),s.init(),i.init()},"interactive"===document.readyState?o():document.addEventListener("readystatechange",function(){"interactive"===document.readyState&&o()})},{"./details-helper":2,"./quick-jump":4,"./style-menu":5}],4:[function(e,t,n){"use strict";var o,r=this&&this.__extends||(o=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},function(e,t){function n(){this.constructor=e}o(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)});Object.defineProperty(n,"__esModule",{value:!0});var i=e("fuse.js"),s=e("preact"),a=s.h,l=s.Component;var c=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return r(t,e),t.prototype.render=function(t){return a("li",null,a("a",{href:"#",onClick:function(e){e.preventDefault(),t.onClick()}},t.title))},t}(l);function u(e){var t=document.querySelector("#page-menu"),n=document.createElement("li");t.insertBefore(n,t.firstChild),s.render(a(c,{onClick:e,title:"Quick Jump"}),t,n)}function d(e,t){return t.length<=e?t:t.slice(0,e)}var h=function(t){function e(){var e=null!==t&&t.apply(this,arguments)||this;return e.linkIndex=0,e.focusPlease=!1,e.navigatedByKeyboard=!1,e}return r(e,t),e.prototype.componentWillMount=function(){var e,t,n,o,r=this;this.setState({searchString:"",isVisible:!1,expanded:{},activeLinkIndex:-1,moduleResults:[]}),e=this.props.baseUrl+"/doc-index.json",t=function(e){r.setState({fuse:new i(e,{threshold:.25,caseSensitive:!0,includeScore:!0,tokenize:!0,keys:[{name:"name",weight:.7},{name:"module",weight:.3}]}),moduleResults:[]})},n=function(e){console&&console.error("could not load 'doc-index.json' for searching",e),r.setState({failedLoading:!0})},(o=new XMLHttpRequest).onreadystatechange=function(){if(o.readyState===XMLHttpRequest.DONE)if(200===o.status){if(t)try{t(JSON.parse(o.responseText))}catch(e){n(o)}}else n&&n(o)},o.open("GET",e,!0),o.send(),document.addEventListener("mousedown",this.hide.bind(this)),document.addEventListener("keydown",function(e){r.state.isVisible&&("Escape"===e.key?r.hide():"ArrowUp"===e.key||"k"===e.key&&e.ctrlKey?(e.preventDefault(),r.navigateLinks(-1)):"ArrowDown"===e.key||"j"===e.key&&e.ctrlKey?(e.preventDefault(),r.navigateLinks(1)):"Enter"===e.key&&0<=r.state.activeLinkIndex&&r.followActiveLink()),"s"===e.key&&"input"!==e.target.tagName.toLowerCase()&&(e.preventDefault(),r.show())})},e.prototype.hide=function(){this.setState({isVisible:!1,searchString:""})},e.prototype.show=function(){this.state.isVisible||(this.focusPlease=!0,this.setState({isVisible:!0,activeLinkIndex:-1}))},e.prototype.toggleVisibility=function(){this.state.isVisible?this.hide():this.show()},e.prototype.navigateLinks=function(e){var t=Math.max(-1,Math.min(this.linkIndex-1,this.state.activeLinkIndex+e));this.navigatedByKeyboard=!0,this.setState({activeLinkIndex:t})},e.prototype.followActiveLink=function(){this.activeLinkAction&&this.activeLinkAction()},e.prototype.updateResults=function(){var e=this.input&&this.input.value||"",t=this.state.fuse.search(e),o={};t.forEach(function(e){var t=e.item.module;(o[t]||(o[t]=[])).push(e)});var r=[],n=function(e){var t=o[e],n=0;t.forEach(function(e){n+=1/e.score}),r.push({module:e,totalScore:1/n,items:t})};for(var i in o)n(i);r.sort(function(e,t){return e.totalScore-t.totalScore}),this.setState({searchString:e,isVisible:!0,moduleResults:r})},e.prototype.componentDidUpdate=function(){if(this.searchResults&&this.activeLink&&this.navigatedByKeyboard){var e=this.activeLink.getClientRects()[0],t=this.searchResults.getClientRects()[0].top;e.bottom>window.innerHeight?this.searchResults.scrollTop+=e.bottom-window.innerHeight+80:e.top<t&&(this.searchResults.scrollTop-=t-e.top+80)}this.focusPlease&&this.input&&this.input.focus(),this.navigatedByKeyboard=!1,this.focusPlease=!1},e.prototype.componentDidMount=function(){this.props.showHideTrigger(this.toggleVisibility.bind(this))},e.prototype.render=function(e,t){var r=this;if(t.failedLoading){var n="file:"==window.location.protocol;return a("div",{id:"search",class:t.isVisible?"":"hidden"},a("div",{id:"search-results"},a("p",{class:"error"},"Failed to load file 'doc-index.json' containing definitions in this package."),n?a("p",{class:"error"},"To use quick jump, load this page with HTTP (from a local static file web server) instead of using the ",a("code",null,"file://")," protocol. (For security reasons, it is not possible to fetch auxiliary files using JS in a HTML page opened with ",a("code",null,"file://"),".)"):[]))}this.linkIndex=0;var o=function(e){e.stopPropagation()},i=d(10,t.moduleResults).map(function(e){return r.renderResultsInModule(e)});return a("div",{id:"search",class:t.isVisible?"":"hidden"},a("div",{id:"search-form",onMouseDown:o},a("input",{placeholder:"Search in package by name",ref:function(e){r.input=e},onFocus:this.show.bind(this),onClick:this.show.bind(this),onInput:this.updateResults.bind(this)})),a("div",{id:"search-results",ref:function(e){r.searchResults=e},onMouseDown:o,onMouseOver:function(e){for(var t=e.target;t&&"function"==typeof t.getAttribute;){var n=t.getAttribute("data-link-index");if("string"==typeof n){var o=parseInt(n,10);r.setState({activeLinkIndex:o});break}t=t.parentNode}}},""===t.searchString?[a(v,null),a(f,null)]:0==i.length?a(g,{searchString:t.searchString}):a("ul",null,i)))},e.prototype.renderResultsInModule=function(e){var n=this,t=e.items,o=e.module,r=this.state.expanded[o]||t.length<=10,i=r?t:d(8,t);return a("li",{class:"search-module"},a("h4",null,o),a("ul",null,i.map(function(e){return t=e.item,a("li",{class:"search-result"},n.navigationLink(n.props.baseUrl+"/"+t.link,{},a(p,{html:t.display_html})));var t}),r?[]:a("li",{class:"more-results"},this.actionLink(function(){var e=Object.assign({},n.state.expanded);e[o]=!0,n.setState({expanded:e})},{},"show "+(t.length-i.length)+" more results from this module"))))},e.prototype.navigationLink=function(e,t){for(var n=this,o=[],r=2;r<arguments.length;r++)o[r-2]=arguments[r];var i=Object.assign({href:e,onClick:this.hide.bind(this)},t);return this.menuLink.apply(this,[i,function(){window.location.href=e,n.hide()}].concat(o))},e.prototype.actionLink=function(t,e){for(var n=[],o=2;o<arguments.length;o++)n[o-2]=arguments[o];var r=Object.assign({href:"#",onClick:function(e){e.preventDefault(),t()}},e);return this.menuLink.apply(this,[r,t].concat(n))},e.prototype.menuLink=function(e,t){for(var n=this,o=[],r=2;r<arguments.length;r++)o[r-2]=arguments[r];var i=this.linkIndex;i===this.state.activeLinkIndex&&(e.class=(e.class?e.class+" ":"")+"active-link",e.ref=function(e){e&&(n.activeLink=e)},this.activeLinkAction=t);var s=Object.assign({"data-link-index":i},e);return this.linkIndex+=1,a.apply(void 0,["a",s].concat(o))},e}(l),p=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return r(t,e),t.prototype.shouldComponentUpdate=function(e){return this.props.html!==e.html},t.prototype.render=function(e){return a("div",{dangerouslySetInnerHTML:{__html:e.html}})},t}(l);function f(){return a("table",{class:"keyboard-shortcuts"},a("tr",null,a("th",null,"Key"),a("th",null,"Shortcut")),a("tr",null,a("td",null,a("span",{class:"key"},"s")),a("td",null,"Open this search box")),a("tr",null,a("td",null,a("span",{class:"key"},"esc")),a("td",null,"Close this search box")),a("tr",null,a("td",null,a("span",{class:"key"},"↓"),",",a("span",{class:"key"},"ctrl")," + ",a("span",{class:"key"},"j")),a("td",null,"Move down in search results")),a("tr",null,a("td",null,a("span",{class:"key"},"↑"),",",a("span",{class:"key"},"ctrl")," + ",a("span",{class:"key"},"k")),a("td",null,"Move up in search results")),a("tr",null,a("td",null,a("span",{class:"key"},"↵")),a("td",null,"Go to active search result")))}function v(){return a("p",null,"You can find any exported type, constructor, class, function or pattern defined in this package by (approximate) name.")}function g(e){var t=[a("p",null,"Your search for '",e.searchString,"' produced the following list of results: ",a("code",null,"[]"),"."),a("p",null,a("code",null,"Nothing")," matches your query for '",e.searchString,"'."),a("p",null,a("code",null,"Left \"no matches for '",e.searchString,"'\" :: Either String (NonEmpty SearchResult)"))];return t[(e.searchString||"a").charCodeAt(0)%t.length]}function m(e,t){s.render(a(h,{baseUrl:e||".",showHideTrigger:t||u}),document.body)}n.init=m,window.quickNav={init:m}},{"fuse.js":6,preact:7}],5:[function(e,t,n){"use strict";var o,r=this&&this.__extends||(o=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},function(e,t){function n(){this.constructor=e}o(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)});Object.defineProperty(n,"__esModule",{value:!0});var i=e("./cookies"),s=e("preact"),a=s.h,l=s.Component;function c(){return Array.prototype.slice.call(document.getElementsByTagName("link")).filter(function(e){return-1!=e.rel.indexOf("style")&&e.title})}function u(e){for(var t=c(),n=null,o=0;o<t.length;o++){var r=t[o];r.disabled=!0,r.title==e&&(n=r)}n?(n.disabled=!1,i.setCookie("haddock-style",e)):(t[0].disabled=!1,i.clearCookie("haddock-style"))}var d=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return r(t,e),t.prototype.render=function(t){return a("li",null,a("a",{href:"#",onClick:function(e){e.preventDefault(),t.onClick()}},t.title))},t}(l);var h=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return r(t,e),t.prototype.componentWillMount=function(){var t=this;document.addEventListener("mousedown",this.hide.bind(this)),document.addEventListener("keydown",function(e){t.state.isVisible&&"Escape"===e.key&&t.hide()})},t.prototype.hide=function(){this.setState({isVisible:!1})},t.prototype.show=function(){this.state.isVisible||this.setState({isVisible:!0})},t.prototype.toggleVisibility=function(){this.state.isVisible?this.hide():this.show()},t.prototype.componentDidMount=function(){this.props.showHideTrigger(this.toggleVisibility.bind(this))},t.prototype.render=function(e,t){var n=this;return a("div",{id:"style",class:t.isVisible?"":"hidden"},a("div",{id:"style-menu",class:"dropdown-menu",onMouseDown:function(e){e.stopPropagation()}},e.styles.map(function(t){return a("button",{type:"button",onClick:function(e){n.hide(),u(t)}},t)})))},t}(l);n.init=function(e){var t,n=c().map(function(e){return e.title});(t=i.getCookie("haddock-style"))&&u(t),s.render(a(h,{showHideTrigger:e||function(e){return function(e,t){if(1<e.length){var n=document.querySelector("#page-menu"),o=document.createElement("li");n.appendChild(o),s.render(a(d,{onClick:t,title:"Styles"}),n,o)}}(n,e)},styles:n}),document.body)}},{"./cookies":1,preact:7}],6:[function(e,t,n){var o,r;o=this,r=function(){return function(n){var o={};function r(e){if(o[e])return o[e].exports;var t=o[e]={i:e,l:!1,exports:{}};return n[e].call(t.exports,t,t.exports,r),t.l=!0,t.exports}return r.m=n,r.c=o,r.i=function(e){return e},r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:n})},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=8)}([function(e,t,n){"use strict";e.exports=function(e){return Array.isArray?Array.isArray(e):"[object Array]"===Object.prototype.toString.call(e)}},function(e,t,n){"use strict";var o=function(){function o(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(e,t,n){return t&&o(e.prototype,t),n&&o(e,n),e}}();var u=n(5),d=n(7),_=n(4),r=function(){function y(e,t){var n=t.location,o=void 0===n?0:n,r=t.distance,i=void 0===r?100:r,s=t.threshold,a=void 0===s?.6:s,l=t.maxPatternLength,c=void 0===l?32:l,u=t.isCaseSensitive,d=void 0!==u&&u,h=t.tokenSeparator,p=void 0===h?/ +/g:h,f=t.findAllMatches,v=void 0!==f&&f,g=t.minMatchCharLength,m=void 0===g?1:g;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,y),this.options={location:o,distance:i,threshold:a,maxPatternLength:c,isCaseSensitive:d,tokenSeparator:p,findAllMatches:v,minMatchCharLength:m},this.pattern=this.options.isCaseSensitive?e:e.toLowerCase(),this.pattern.length<=c&&(this.patternAlphabet=_(this.pattern))}return o(y,[{key:"search",value:function(e){if(this.options.isCaseSensitive||(e=e.toLowerCase()),this.pattern===e)return{isMatch:!0,score:0,matchedIndices:[[0,e.length-1]]};var t=this.options,n=t.maxPatternLength,o=t.tokenSeparator;if(this.pattern.length>n)return u(e,this.pattern,o);var r=this.options,i=r.location,s=r.distance,a=r.threshold,l=r.findAllMatches,c=r.minMatchCharLength;return d(e,this.pattern,this.patternAlphabet,{location:i,distance:s,threshold:a,findAllMatches:l,minMatchCharLength:c})}}]),y}();e.exports=r},function(e,t,n){"use strict";var u=n(0);e.exports=function(e,t){return function e(t,n,o){if(n){var r=n.indexOf("."),i=n,s=null;-1!==r&&(i=n.slice(0,r),s=n.slice(r+1));var a=t[i];if(null!=a)if(s||"string"!=typeof a&&"number"!=typeof a)if(u(a))for(var l=0,c=a.length;l<c;l+=1)e(a[l],s,o);else s&&e(a,s,o);else o.push(a.toString())}else o.push(t);return o}(e,t,[])}},function(e,t,n){"use strict";e.exports=function(){for(var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:[],t=1<arguments.length&&void 0!==arguments[1]?arguments[1]:1,n=[],o=-1,r=-1,i=0,s=e.length;i<s;i+=1){var a=e[i];a&&-1===o?o=i:a||-1===o||(t<=(r=i-1)-o+1&&n.push([o,r]),o=-1)}return e[i-1]&&t<=i-o&&n.push([o,i-1]),n}},function(e,t,n){"use strict";e.exports=function(e){for(var t={},n=e.length,o=0;o<n;o+=1)t[e.charAt(o)]=0;for(var r=0;r<n;r+=1)t[e.charAt(r)]|=1<<n-r-1;return t}},function(e,t,n){"use strict";var u=/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g;e.exports=function(e,t){var n=2<arguments.length&&void 0!==arguments[2]?arguments[2]:/ +/g,o=new RegExp(t.replace(u,"\\$&").replace(n,"|")),r=e.match(o),i=!!r,s=[];if(i)for(var a=0,l=r.length;a<l;a+=1){var c=r[a];s.push([e.indexOf(c),c.length-1])}return{score:i?.5:1,isMatch:i,matchedIndices:s}}},function(e,t,n){"use strict";e.exports=function(e,t){var n=t.errors,o=void 0===n?0:n,r=t.currentLocation,i=void 0===r?0:r,s=t.expectedLocation,a=void 0===s?0:s,l=t.distance,c=void 0===l?100:l,u=o/e.length,d=Math.abs(a-i);return c?u+d/c:d?1:u}},function(e,t,n){"use strict";var V=n(6),D=n(3);e.exports=function(e,t,n,o){for(var r=o.location,i=void 0===r?0:r,s=o.distance,a=void 0===s?100:s,l=o.threshold,c=void 0===l?.6:l,u=o.findAllMatches,d=void 0!==u&&u,h=o.minMatchCharLength,p=void 0===h?1:h,f=i,v=e.length,g=c,m=e.indexOf(t,f),y=t.length,_=[],b=0;b<v;b+=1)_[b]=0;if(-1!==m){var k=V(t,{errors:0,currentLocation:m,expectedLocation:f,distance:a});if(g=Math.min(k,g),-1!==(m=e.lastIndexOf(t,f+y))){var S=V(t,{errors:0,currentLocation:m,expectedLocation:f,distance:a});g=Math.min(S,g)}}m=-1;for(var x=[],w=1,C=y+v,L=1<<y-1,M=0;M<y;M+=1){for(var I=0,E=C;I<E;){V(t,{errors:M,currentLocation:f+E,expectedLocation:f,distance:a})<=g?I=E:C=E,E=Math.floor((C-I)/2+I)}C=E;var O=Math.max(1,f-E+1),A=d?v:Math.min(f+E,v)+y,T=Array(A+2);T[A+1]=(1<<M)-1;for(var N=A;O<=N;N-=1){var P=N-1,j=n[e.charAt(P)];if(j&&(_[P]=1),T[N]=(T[N+1]<<1|1)&j,0!==M&&(T[N]|=(x[N+1]|x[N])<<1|1|x[N+1]),T[N]&L&&(w=V(t,{errors:M,currentLocation:P,expectedLocation:f,distance:a}))<=g){if(g=w,(m=P)<=f)break;O=Math.max(1,2*f-m)}}if(g<V(t,{errors:M+1,currentLocation:f,expectedLocation:f,distance:a}))break;x=T}return{isMatch:0<=m,score:0===w?.001:w,matchedIndices:D(_,p)}}},function(e,t,n){"use strict";var o=function(){function o(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(e,t,n){return t&&o(e.prototype,t),n&&o(e,n),e}}();var i=n(1),R=n(2),V=n(0),r=function(){function U(e,t){var n=t.location,o=void 0===n?0:n,r=t.distance,i=void 0===r?100:r,s=t.threshold,a=void 0===s?.6:s,l=t.maxPatternLength,c=void 0===l?32:l,u=t.caseSensitive,d=void 0!==u&&u,h=t.tokenSeparator,p=void 0===h?/ +/g:h,f=t.findAllMatches,v=void 0!==f&&f,g=t.minMatchCharLength,m=void 0===g?1:g,y=t.id,_=void 0===y?null:y,b=t.keys,k=void 0===b?[]:b,S=t.shouldSort,x=void 0===S||S,w=t.getFn,C=void 0===w?R:w,L=t.sortFn,M=void 0===L?function(e,t){return e.score-t.score}:L,I=t.tokenize,E=void 0!==I&&I,O=t.matchAllTokens,A=void 0!==O&&O,T=t.includeMatches,N=void 0!==T&&T,P=t.includeScore,j=void 0!==P&&P,V=t.verbose,D=void 0!==V&&V;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,U),this.options={location:o,distance:i,threshold:a,maxPatternLength:c,isCaseSensitive:d,tokenSeparator:p,findAllMatches:v,minMatchCharLength:m,id:_,keys:k,includeMatches:N,includeScore:j,shouldSort:x,getFn:C,sortFn:M,verbose:D,tokenize:E,matchAllTokens:A},this.setCollection(e)}return o(U,[{key:"setCollection",value:function(e){return this.list=e}},{key:"search",value:function(e){this._log('---------\nSearch pattern: "'+e+'"');var t=this._prepareSearchers(e),n=t.tokenSearchers,o=t.fullSearcher,r=this._search(n,o),i=r.weights,s=r.results;return this._computeScore(i,s),this.options.shouldSort&&this._sort(s),this._format(s)}},{key:"_prepareSearchers",value:function(){var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:"",t=[];if(this.options.tokenize)for(var n=e.split(this.options.tokenSeparator),o=0,r=n.length;o<r;o+=1)t.push(new i(n[o],this.options));return{tokenSearchers:t,fullSearcher:new i(e,this.options)}}},{key:"_search",value:function(){var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:[],t=arguments[1],n=this.list,o={},r=[];if("string"==typeof n[0]){for(var i=0,s=n.length;i<s;i+=1)this._analyze({key:"",value:n[i],record:i,index:i},{resultMap:o,results:r,tokenSearchers:e,fullSearcher:t});return{weights:null,results:r}}for(var a={},l=0,c=n.length;l<c;l+=1)for(var u=n[l],d=0,h=this.options.keys.length;d<h;d+=1){var p=this.options.keys[d];if("string"!=typeof p){if(a[p.name]={weight:1-p.weight||1},p.weight<=0||1<p.weight)throw new Error("Key weight has to be > 0 and <= 1");p=p.name}else a[p]={weight:1};this._analyze({key:p,value:this.options.getFn(u,p),record:u,index:l},{resultMap:o,results:r,tokenSearchers:e,fullSearcher:t})}return{weights:a,results:r}}},{key:"_analyze",value:function(e,t){var n=e.key,o=e.arrayIndex,r=void 0===o?-1:o,i=e.value,s=e.record,a=e.index,l=t.tokenSearchers,c=void 0===l?[]:l,u=t.fullSearcher,d=void 0===u?[]:u,h=t.resultMap,p=void 0===h?{}:h,f=t.results,v=void 0===f?[]:f;if(null!=i){var g=!1,m=-1,y=0;if("string"==typeof i){this._log("\nKey: "+(""===n?"-":n));var _=d.search(i);if(this._log('Full text: "'+i+'", score: '+_.score),this.options.tokenize){for(var b=i.split(this.options.tokenSeparator),k=[],S=0;S<c.length;S+=1){var x=c[S];this._log('\nPattern: "'+x.pattern+'"');for(var w=!1,C=0;C<b.length;C+=1){var L=b[C],M=x.search(L),I={};M.isMatch?(I[L]=M.score,w=g=!0,k.push(M.score)):(I[L]=1,this.options.matchAllTokens||k.push(1)),this._log('Token: "'+L+'", score: '+I[L])}w&&(y+=1)}m=k[0];for(var E=k.length,O=1;O<E;O+=1)m+=k[O];m/=E,this._log("Token score average:",m)}var A=_.score;-1<m&&(A=(A+m)/2),this._log("Score average:",A);var T=!this.options.tokenize||!this.options.matchAllTokens||y>=c.length;if(this._log("\nCheck Matches: "+T),(g||_.isMatch)&&T){var N=p[a];N?N.output.push({key:n,arrayIndex:r,value:i,score:A,matchedIndices:_.matchedIndices}):(p[a]={item:s,output:[{key:n,arrayIndex:r,value:i,score:A,matchedIndices:_.matchedIndices}]},v.push(p[a]))}}else if(V(i))for(var P=0,j=i.length;P<j;P+=1)this._analyze({key:n,arrayIndex:P,value:i[P],record:s,index:a},{resultMap:p,results:v,tokenSearchers:c,fullSearcher:d})}}},{key:"_computeScore",value:function(e,t){this._log("\n\nComputing score:\n");for(var n=0,o=t.length;n<o;n+=1){for(var r=t[n].output,i=r.length,s=1,a=1,l=0;l<i;l+=1){var c=e?e[r[l].key].weight:1,u=(1===c?r[l].score:r[l].score||.001)*c;1!==c?a=Math.min(a,u):s*=r[l].nScore=u}t[n].score=1===a?s:a,this._log(t[n])}}},{key:"_sort",value:function(e){this._log("\n\nSorting...."),e.sort(this.options.sortFn)}},{key:"_format",value:function(e){var t=[];this.options.verbose&&this._log("\n\nOutput:\n\n",JSON.stringify(e));var n=[];this.options.includeMatches&&n.push(function(e,t){var n=e.output;t.matches=[];for(var o=0,r=n.length;o<r;o+=1){var i=n[o];if(0!==i.matchedIndices.length){var s={indices:i.matchedIndices,value:i.value};i.key&&(s.key=i.key),i.hasOwnProperty("arrayIndex")&&-1<i.arrayIndex&&(s.arrayIndex=i.arrayIndex),t.matches.push(s)}}}),this.options.includeScore&&n.push(function(e,t){t.score=e.score});for(var o=0,r=e.length;o<r;o+=1){var i=e[o];if(this.options.id&&(i.item=this.options.getFn(i.item,this.options.id)[0]),n.length){for(var s={item:i.item},a=0,l=n.length;a<l;a+=1)n[a](i,s);t.push(s)}else t.push(i.item)}return t}},{key:"_log",value:function(){var e;this.options.verbose&&(e=console).log.apply(e,arguments)}}]),U}();e.exports=r}])},"object"==typeof n&&"object"==typeof t?t.exports=r():"function"==typeof define&&define.amd?define("Fuse",[],r):"object"==typeof n?n.Fuse=r():o.Fuse=r()},{}],7:[function(e,y,t){!function(){"use strict";function n(e,t){var n,o,r,i,s=d;for(i=arguments.length;2<i--;)u.push(arguments[i]);for(t&&null!=t.children&&(u.length||u.push(t.children),delete t.children);u.length;)if((o=u.pop())&&void 0!==o.pop)for(i=o.length;i--;)u.push(o[i]);else"boolean"==typeof o&&(o=null),(r="function"!=typeof e)&&(null==o?o="":"number"==typeof o?o=String(o):"string"!=typeof o&&(r=!1)),r&&n?s[s.length-1]+=o:s===d?s=[o]:s.push(o),n=r;var a=new c;return a.nodeName=e,a.children=s,a.attributes=null==t?void 0:t,a.key=null==t?void 0:t.key,void 0!==D.vnode&&D.vnode(a),a}function L(e,t){for(var n in t)e[n]=t[n];return e}function i(e){!e.__d&&(e.__d=!0)&&1==p.push(e)&&(D.debounceRendering||r)(t)}function t(){var e,t=p;for(p=[];e=t.pop();)e.__d&&j(e)}function C(e,t){return e.__n===t||e.nodeName.toLowerCase()===t.toLowerCase()}function M(e){var t=L({},e.attributes);t.children=e.children;var n=e.nodeName.defaultProps;if(void 0!==n)for(var o in n)void 0===t[o]&&(t[o]=n[o]);return t}function I(e){var t=e.parentNode;t&&t.removeChild(e)}function v(e,t,n,o,r){if("className"===t&&(t="class"),"key"===t);else if("ref"===t)n&&n(null),o&&o(e);else if("class"!==t||r)if("style"===t){if(o&&"string"!=typeof o&&"string"!=typeof n||(e.style.cssText=o||""),o&&"object"==typeof o){if("string"!=typeof n)for(var i in n)i in o||(e.style[i]="");for(var i in o)e.style[i]="number"==typeof o[i]&&!1===h.test(i)?o[i]+"px":o[i]}}else if("dangerouslySetInnerHTML"===t)o&&(e.innerHTML=o.__html||"");else if("o"==t[0]&&"n"==t[1]){var s=t!==(t=t.replace(/Capture$/,""));t=t.toLowerCase().substring(2),o?n||e.addEventListener(t,l,s):e.removeEventListener(t,l,s),(e.__l||(e.__l={}))[t]=o}else if("list"!==t&&"type"!==t&&!r&&t in e){try{e[t]=null==o?"":o}catch(e){}null!=o&&!1!==o||"spellcheck"==t||e.removeAttribute(t)}else{var a=r&&t!==(t=t.replace(/^xlink:?/,""));null==o||!1===o?a?e.removeAttributeNS("http://www.w3.org/1999/xlink",t.toLowerCase()):e.removeAttribute(t):"function"!=typeof o&&(a?e.setAttributeNS("http://www.w3.org/1999/xlink",t.toLowerCase(),o):e.setAttribute(t,o))}else e.className=o||""}function l(e){return this.__l[e.type](D.event&&D.event(e)||e)}function E(){for(var e;e=U.pop();)D.afterMount&&D.afterMount(e),e.componentDidMount&&e.componentDidMount()}function O(e,t,n,o,r,i){R++||(g=null!=r&&void 0!==r.ownerSVGElement,m=null!=e&&!("__preactattr_"in e));var s=A(e,t,n,o,i);return r&&s.parentNode!==r&&r.appendChild(s),--R||(m=!1,i||E()),s}function A(e,t,n,o,r){var i=e,s=g;if(null!=t&&"boolean"!=typeof t||(t=""),"string"==typeof t||"number"==typeof t)return e&&void 0!==e.splitText&&e.parentNode&&(!e._component||r)?e.nodeValue!=t&&(e.nodeValue=t):(i=document.createTextNode(t),e&&(e.parentNode&&e.parentNode.replaceChild(i,e),T(e,!0))),i.__preactattr_=!0,i;var a,l,c=t.nodeName;if("function"==typeof c)return function(e,t,n,o){var r=e&&e._component,i=r,s=e,a=r&&e._componentConstructor===t.nodeName,l=a,c=M(t);for(;r&&!l&&(r=r.__u);)l=r.constructor===t.nodeName;r&&l&&(!o||r._component)?(P(r,c,3,n,o),e=r.base):(i&&!a&&(V(i),e=s=null),r=N(t.nodeName,c,n),e&&!r.__b&&(r.__b=e,s=null),P(r,c,1,n,o),e=r.base,s&&e!==s&&(s._component=null,T(s,!1)));return e}(e,t,n,o);if(g="svg"===c||"foreignObject"!==c&&g,c=String(c),(!e||!C(e,c))&&(a=c,(l=g?document.createElementNS("http://www.w3.org/2000/svg",a):document.createElement(a)).__n=a,i=l,e)){for(;e.firstChild;)i.appendChild(e.firstChild);e.parentNode&&e.parentNode.replaceChild(i,e),T(e,!0)}var u=i.firstChild,d=i.__preactattr_,h=t.children;if(null==d){d=i.__preactattr_={};for(var p=i.attributes,f=p.length;f--;)d[p[f].name]=p[f].value}return!m&&h&&1===h.length&&"string"==typeof h[0]&&null!=u&&void 0!==u.splitText&&null==u.nextSibling?u.nodeValue!=h[0]&&(u.nodeValue=h[0]):(h&&h.length||null!=u)&&function(e,t,n,o,r){var i,s,a,l,c,u=e.childNodes,d=[],h={},p=0,f=0,v=u.length,g=0,m=t?t.length:0;if(0!==v)for(var y=0;y<v;y++){var _=u[y],b=_.__preactattr_,k=m&&b?_._component?_._component.__k:b.key:null;null!=k?(p++,h[k]=_):(b||(void 0!==_.splitText?!r||_.nodeValue.trim():r))&&(d[g++]=_)}if(0!==m)for(var y=0;y<m;y++){l=t[y],c=null;var k=l.key;if(null!=k)p&&void 0!==h[k]&&(c=h[k],h[k]=void 0,p--);else if(f<g)for(i=f;i<g;i++)if(void 0!==d[i]&&(S=s=d[i],w=r,"string"==typeof(x=l)||"number"==typeof x?void 0!==S.splitText:"string"==typeof x.nodeName?!S._componentConstructor&&C(S,x.nodeName):w||S._componentConstructor===x.nodeName)){c=s,d[i]=void 0,i===g-1&&g--,i===f&&f++;break}c=A(c,l,n,o),a=u[y],c&&c!==e&&c!==a&&(null==a?e.appendChild(c):c===a.nextSibling?I(a):e.insertBefore(c,a))}var S,x,w;if(p)for(var y in h)void 0!==h[y]&&T(h[y],!1);for(;f<=g;)void 0!==(c=d[g--])&&T(c,!1)}(i,h,n,o,m||null!=d.dangerouslySetInnerHTML),function(e,t,n){var o;for(o in n)t&&null!=t[o]||null==n[o]||v(e,o,n[o],n[o]=void 0,g);for(o in t)"children"===o||"innerHTML"===o||o in n&&t[o]===("value"===o||"checked"===o?e[o]:n[o])||v(e,o,n[o],n[o]=t[o],g)}(i,t.attributes,d),g=s,i}function T(e,t){var n=e._component;n?V(n):(null!=e.__preactattr_&&e.__preactattr_.ref&&e.__preactattr_.ref(null),!1!==t&&null!=e.__preactattr_||I(e),o(e))}function o(e){for(e=e.lastChild;e;){var t=e.previousSibling;T(e,!0),e=t}}function N(e,t,n){var o,r=f.length;for(e.prototype&&e.prototype.render?(o=new e(t,n),a.call(o,t,n)):((o=new a(t,n)).constructor=e,o.render=s);r--;)if(f[r].constructor===e)return o.__b=f[r].__b,f.splice(r,1),o;return o}function s(e,t,n){return this.constructor(e,n)}function P(e,t,n,o,r){e.__x||(e.__x=!0,e.__r=t.ref,e.__k=t.key,delete t.ref,delete t.key,void 0===e.constructor.getDerivedStateFromProps&&(!e.base||r?e.componentWillMount&&e.componentWillMount():e.componentWillReceiveProps&&e.componentWillReceiveProps(t,o)),o&&o!==e.context&&(e.__c||(e.__c=e.context),e.context=o),e.__p||(e.__p=e.props),e.props=t,e.__x=!1,0!==n&&(1!==n&&!1===D.syncComponentUpdates&&e.base?i(e):j(e,1,r)),e.__r&&e.__r(e))}function j(e,t,n,o){if(!e.__x){var r,i,s,a=e.props,l=e.state,c=e.context,u=e.__p||a,d=e.__s||l,h=e.__c||c,p=e.base,f=e.__b,v=p||f,g=e._component,m=!1,y=h;if(e.constructor.getDerivedStateFromProps&&(l=L(L({},l),e.constructor.getDerivedStateFromProps(a,l)),e.state=l),p&&(e.props=u,e.state=d,e.context=h,2!==t&&e.shouldComponentUpdate&&!1===e.shouldComponentUpdate(a,l,c)?m=!0:e.componentWillUpdate&&e.componentWillUpdate(a,l,c),e.props=a,e.state=l,e.context=c),e.__p=e.__s=e.__c=e.__b=null,e.__d=!1,!m){r=e.render(a,l,c),e.getChildContext&&(c=L(L({},c),e.getChildContext())),p&&e.getSnapshotBeforeUpdate&&(y=e.getSnapshotBeforeUpdate(u,d));var _,b,k=r&&r.nodeName;if("function"==typeof k){var S=M(r);(i=g)&&i.constructor===k&&S.key==i.__k?P(i,S,1,c,!1):(_=i,e._component=i=N(k,S,c),i.__b=i.__b||f,i.__u=e,P(i,S,0,c,!1),j(i,1,n,!0)),b=i.base}else s=v,(_=g)&&(s=e._component=null),(v||1===t)&&(s&&(s._component=null),b=O(s,r,c,n||!p,v&&v.parentNode,!0));if(v&&b!==v&&i!==g){var x=v.parentNode;x&&b!==x&&(x.replaceChild(b,v),_||(v._component=null,T(v,!1)))}if(_&&V(_),(e.base=b)&&!o){for(var w=e,C=e;C=C.__u;)(w=C).base=b;b._component=w,b._componentConstructor=w.constructor}}for(!p||n?U.unshift(e):m||(e.componentDidUpdate&&e.componentDidUpdate(u,d,y),D.afterUpdate&&D.afterUpdate(e));e.__h.length;)e.__h.pop().call(e);R||o||E()}}function V(e){D.beforeUnmount&&D.beforeUnmount(e);var t=e.base;e.__x=!0,e.componentWillUnmount&&e.componentWillUnmount(),e.base=null;var n=e._component;n?V(n):t&&(t.__preactattr_&&t.__preactattr_.ref&&t.__preactattr_.ref(null),I(e.__b=t),f.push(e),o(t)),e.__r&&e.__r(null)}function a(e,t){this.__d=!0,this.context=t,this.props=e,this.state=this.state||{},this.__h=[]}var c=function(){},D={},u=[],d=[],r="function"==typeof Promise?Promise.resolve().then.bind(Promise.resolve()):setTimeout,h=/acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i,p=[],U=[],R=0,g=!1,m=!1,f=[];L(a.prototype,{setState:function(e,t){this.__s||(this.__s=this.state),this.state=L(L({},this.state),"function"==typeof e?e(this.state,this.props):e),t&&this.__h.push(t),i(this)},forceUpdate:function(e){e&&this.__h.push(e),j(this,2)},render:function(){}});var e={h:n,createElement:n,cloneElement:function(e,t){return n(e.nodeName,L(L({},e.attributes),t),2<arguments.length?[].slice.call(arguments,2):e.children)},Component:a,render:function(e,t,n){return O(n,e,{},!1,t,!1)},rerender:t,options:D};void 0!==y?y.exports=e:self.preact=e}()},{}]},{},[3]);  //# sourceMappingURL=haddock-bundle.min.js.map diff --git a/haddock-api/resources/html/js-src/details-helper.ts b/haddock-api/resources/html/js-src/details-helper.ts deleted file mode 100644 index f13ac905..00000000 --- a/haddock-api/resources/html/js-src/details-helper.ts +++ /dev/null @@ -1,106 +0,0 @@ -import {getCookie} from "./cookies"; - -interface HTMLDetailsElement extends HTMLElement { -  open: boolean -} - -interface DetailsInfo { -  element: HTMLDetailsElement -  openByDefault: boolean -  toggles: HTMLElement[] -} - -// Global state -const detailsRegistry: { [id: string]: DetailsInfo } = {}; -const toggled: { [id: string]: true } = {}; /* stores which <details> are not in their default state */ - -function lookupDetailsRegistry(id: string): DetailsInfo { -  const info = detailsRegistry[id]; -  if (info == undefined) { throw new Error(`could not find <details> element with id '${id}'`); } -  return info; -} - -function onDetailsToggle(ev: Event) { -  const element = ev.target as HTMLDetailsElement; -  const id = element.id; -  const info = lookupDetailsRegistry(id); -  const isOpen = info.element.open; -  for (const toggle of info.toggles) { -    if (toggle.classList.contains('details-toggle-control')) { -      toggle.classList.add(isOpen ? 'collapser' : 'expander'); -      toggle.classList.remove(isOpen ? 'expander' : 'collapser'); -    } -  } -  if (element.open == info.openByDefault) { -    delete toggled[id]; -  } else { -    toggled[id] = true; -  } -  rememberToggled(); -} - -function gatherDetailsElements() { -  const els: HTMLDetailsElement[] = Array.prototype.slice.call(document.getElementsByTagName('details')); -  for (const el of els) { -    if (typeof el.id == "string" && el.id.length > 0) { -      detailsRegistry[el.id] = { -        element: el, -        openByDefault: !!el.open, -        toggles: [] // added later -      }; -      el.addEventListener('toggle', onDetailsToggle); -    } -  } -} - -function toggleDetails(id: string) { -  const {element} = lookupDetailsRegistry(id); -  element.open = !element.open; -} - -function rememberToggled() { -  const sections: string[] = Object.keys(toggled); -  // cookie specific to this page; don't use setCookie which sets path=/ -  document.cookie = "toggled=" + encodeURIComponent(sections.join('+')); -} - -function restoreToggled() { -  const cookie = getCookie("toggled"); -  if (!cookie) { return; } -  const ids = cookie.split('+'); -  for (const id of ids) { -    const info = detailsRegistry[id]; -    toggled[id] = true; -    if (info) { -      info.element.open = !info.element.open; -    } -  } -} - -function onToggleClick(ev: MouseEvent) { -  ev.preventDefault(); -  const toggle = ev.currentTarget as HTMLElement; -  const id = toggle.getAttribute('data-details-id'); -  if (!id) { throw new Error("element with class 'details-toggle' has no 'data-details-id' attribute!"); } -  toggleDetails(id); -} - -function initCollapseToggles() { -  const toggles: HTMLElement[] = Array.prototype.slice.call(document.getElementsByClassName('details-toggle')); -  toggles.forEach(toggle => { -    const id = toggle.getAttribute('data-details-id'); -    if (!id) { throw new Error("element with class 'details-toggle' has no 'data-details-id' attribute!"); } -    const info = lookupDetailsRegistry(id); -    info.toggles.push(toggle); -    toggle.addEventListener('click', onToggleClick); -    if (toggle.classList.contains('details-toggle-control')) { -      toggle.classList.add(info.element.open ? 'collapser' : 'expander'); -    } -  }); -} - -export function init() { -  gatherDetailsElements(); -  restoreToggled(); -  initCollapseToggles(); -}
\ No newline at end of file diff --git a/haddock-api/resources/html/js-src/details-helper.tsx b/haddock-api/resources/html/js-src/details-helper.tsx new file mode 100644 index 00000000..871b5417 --- /dev/null +++ b/haddock-api/resources/html/js-src/details-helper.tsx @@ -0,0 +1,464 @@ +// This file implements the UI and logic for collapsing and expanding +// instance lists ("details"). +// +// A configuration ('GlobalConfig') controlled by the UI is persisted +// in local storage in the user's browser. The configuration includes: +// +// * a global default state ('defaultInstanceState') for all instance +//   lists. The possible values for the global default are "collapsed" +//   and "expanded". +// +// * a global boolean option ('rememberToggles') to remember which +//   specific instance lists are not in the default state (e.g. which +//   instance lists are expanded when the default is "collapsed"). +// +// * a local / per-page record of which specific instance lists are +//   not in the default state, when the global option +//   ('rememberToggles') to remember this info is enabled. +// +// The UI consists of an Instances menu with buttons for expanding and +// collapsing all instance lists in the current module, a checkbox for +// setting the global default state, and a checkbox to enable +// remembering which instance lists are not in the global default +// state. Also, each instance list on each module page has buttons for +// collapsing and expanding. +// +// The logic of the UI is as follows: +// +// * setting the global default state erases any record of which +//   specific instances are in the non-default state, and collapses or +//   expands all instance lists on the current page to be in the +//   global default state. +// +// * changing boolean option for remembering which specific instance +//   lists are not in the default state erases any existing record of +//   which instances are not in the default state across all pages, +//   and updates the record for the current page when the option is +//   set to true. No collapsing or expanding is done. +// +// * toggling the collapse/expand state of a specific instance list +//   causes the state of that specific instance list to be recorded in +//   the persisted configuration iff the new state of that specific +//   instance list is different from the global default state, and the +//   option to remember instance list states is enabled. There are two +//   ways to toggle the collapse/expand state of a specific instance, +//   by clicking its collapse/expand button, and by clicking the +//   "collapse all" or "expand all" button in the Instances menu. +// +// This file also implements an association between elements (with +// class "details-toggle" and "details-toggle-control") that can be +// clicked to expand/collapse <details> elements, and the details +// elements themselves. Note that this covers both <details> elements +// that list instances -- what the above explained UI and logic is +// concerned with -- and details about individual instances themselves +// -- which the above is not concerend with. The association includes +// adding event listeners that change CSS classes back and forth +// between "expander" and "collapser"; these classes determine whether +// an element is adorned with a right arrow ("expander") or a down +// arrow ("collapser"). I don't understand why we don't directly use +// the the HTML <summary> element type to allow the <details> elements +// to be directly clickable. +import preact = require("preact"); + +const { h, Component } = preact; + +enum DefaultState { Closed, Open } + +interface GlobalConfig { +  defaultInstanceState: DefaultState +  rememberToggles: boolean +} + +// Hackage domain-wide config +const globalConfig: GlobalConfig = { +  defaultInstanceState: DefaultState.Open, +  rememberToggles: true, +}; + +class PreferencesButton extends Component<any, any> { +  render(props: { title: string, onClick: () => void }) { +    function onClick(e: Event) { +      e.preventDefault(); +      props.onClick(); +    } +    return <li><a href="#" onClick={onClick}>{props.title}</a></li>; +  } +} + +function addPreferencesButton(action: () => void) { +  const pageMenu = document.querySelector('#page-menu') as HTMLUListElement; +  const dummy = document.createElement('li'); +  pageMenu.insertBefore(dummy, pageMenu.firstChild); +  preact.render(<PreferencesButton onClick={action} title="Instances" />, pageMenu, dummy); +} + +type PreferencesProps = { +  showHideTrigger: (action: () => void) => void +} + +type PreferencesState = { +  isVisible: boolean +} + +class Preferences extends Component<PreferencesProps, PreferencesState> { +  componentWillMount() { +    document.addEventListener('mousedown', this.hide.bind(this)); + +    document.addEventListener('keydown', (e) => { +      if (this.state.isVisible) { +        if (e.key === 'Escape') { +          this.hide(); +        } +      } +    }) +  } + +  hide() { +    this.setState({ isVisible: false }); +  } + +  show() { +    if (!this.state.isVisible) { +      this.setState({ isVisible: true }); +    } +  } + +  toggleVisibility() { +    if (this.state.isVisible) { +      this.hide(); +    } else { +      this.show(); +    } +  } + +  componentDidMount() { +    this.props.showHideTrigger(this.toggleVisibility.bind(this)); +  } + +  render(props: PreferencesProps, state: PreferencesState) { +    const stopPropagation = (e: Event) => { e.stopPropagation(); }; + +    return <div id="preferences" class={state.isVisible ? '' : 'hidden'}> +        <div id="preferences-menu" class="dropdown-menu" onMouseDown={stopPropagation}> +          <PreferencesMenu /> +        </div> +      </div>; +  } +} + +function storeGlobalConfig() { +  const json = JSON.stringify(globalConfig); +  try { +    // https://developer.mozilla.org/en-US/docs/Web/API/Storage/setItem#Exceptions. +    localStorage.setItem('global', json); +  } catch (e) {} +} + +var globalConfigLoaded: boolean = false; + +function loadGlobalConfig() { +  if (globalConfigLoaded) { return; } +  globalConfigLoaded = true; +  const global = localStorage.getItem('global'); +  if (!global) { return; } +  try { +    const globalConfig_ = JSON.parse(global); +    globalConfig.defaultInstanceState = globalConfig_.defaultInstanceState; +    globalConfig.rememberToggles = globalConfig_.rememberToggles; +  } catch(e) { +    // Gracefully handle errors related to changed config format. +    if (e instanceof SyntaxError || e instanceof TypeError) { +      localStorage.removeItem('global'); +    } else { +      throw e; +    } +  } +} + +function setDefaultInstanceState(s: DefaultState) { +  return (e: Event) => { +    globalConfig.defaultInstanceState = s; +    putInstanceListsInDefaultState(); +    storeGlobalConfig(); +    clearLocalStorage(); +    storeLocalConfig(); +  } +} + +function setRememberToggles(e: Event) { +  const checked: boolean = (e as any).target.checked; +  globalConfig.rememberToggles = checked; +  storeGlobalConfig(); +  clearLocalStorage(); +  storeLocalConfig(); +} + +// Click event consumer for "default collapse" instance menu check box. +function defaultCollapseOnClick(e: Event) { +  const us = document.getElementById('default-collapse-instances') as HTMLInputElement; +  if (us !== null) { +    if (us.checked) { +      setDefaultInstanceState(DefaultState.Closed)(e); +    } else { +      setDefaultInstanceState(DefaultState.Open)(e); +    } +  } +} + +// Instances menu. +function PreferencesMenu() { +  loadGlobalConfig(); +  return <div> +      <div> +        <button type="button" +                onClick={expandAllInstances}> +        Expand All Instances +        </button> +        <button type="button" +                onClick={collapseAllInstances}> +        Collapse All Instances +        </button> +      </div> +      <div> +        <input type="checkbox" +               id="default-collapse-instances" +               name="default-instance-state" +               checked={globalConfig.defaultInstanceState===DefaultState.Closed} +               onClick={defaultCollapseOnClick}></input> + +        <span>Collapse All Instances By Default</span> +      </div> +      <div> +        <input type="checkbox" +               id="remember-toggles" +               name="remember-toggles" +               checked={globalConfig.rememberToggles} +               onClick={setRememberToggles}></input> +        <label for="remember-toggles">Remember Manually Collapsed/Expanded Instances</label> +      </div> +    </div>; +} + +interface HTMLDetailsElement extends HTMLElement { +  open: boolean +} + +interface DetailsInfo { +  element: HTMLDetailsElement +  // Here 'toggles' is the list of all elements of class +  // 'details-toggle-control' that control toggling 'element'. I +  // believe this list is always length zero or one. +  toggles: HTMLElement[] +} + +// Mapping from <details> elements to their info. +const detailsRegistry: { [id: string]: DetailsInfo } = {}; + +function lookupDetailsRegistry(id: string): DetailsInfo { +  const info = detailsRegistry[id]; +  if (info == undefined) { throw new Error(`could not find <details> element with id '${id}'`); } +  return info; +} + +// Return true iff instance lists are open by default. +function getDefaultOpenSetting(): boolean { +  return globalConfig.defaultInstanceState == DefaultState.Open; +} + +// Event handler for "toggle" events, which are triggered when a +// <details> element's "open" property changes.  We don't deal with +// any config stuff here, because we only change configs in response +// to mouse clicks. In contrast, for example, this event is triggred +// automatically once for every <details> element when the user clicks +// the "collapse all elements" button. +function onToggleEvent(ev: Event) { +  const element = ev.target as HTMLDetailsElement; +  const id = element.id; +  const info = lookupDetailsRegistry(id); +  const isOpen = info.element.open; +  // Update the CSS of the toggle element users can click on to toggle +  // 'element'. The "collapser" and "expander" classes control what +  // kind of arrow appears next to the 'toggle' element. +  for (const toggle of info.toggles) { +    if (toggle.classList.contains('details-toggle-control')) { +      toggle.classList.add(isOpen ? 'collapser' : 'expander'); +      toggle.classList.remove(isOpen ? 'expander' : 'collapser'); +    } +  } +} + +function gatherDetailsElements() { +  const els: HTMLDetailsElement[] = Array.prototype.slice.call(document.getElementsByTagName('details')); +  for (const el of els) { +    if (typeof el.id == "string" && el.id.length > 0) { +      detailsRegistry[el.id] = { +        element: el, +        toggles: [] // Populated later by 'initCollapseToggles'. +      }; +      el.addEventListener('toggle', onToggleEvent); +    } +  } +} + +// Return the id of the <details> element that the given 'toggle' +// element toggles. +function getDataDetailsId(toggle: Element): string { +  const id = toggle.getAttribute('data-details-id'); +  if (!id) { throw new Error("element with class " + toggle + " has no 'data-details-id' attribute!"); } +  return id; +} + +// Toggle the "open" state of a <details> element when that element's +// toggle element is clicked. +function toggleDetails(toggle: Element) { +  const id = getDataDetailsId(toggle); +  const {element} = lookupDetailsRegistry(id); +  element.open = !element.open; +} + +// Prefix for local keys used with local storage. Idea is that other +// modules could also use local storage with a different prefix and we +// wouldn't step on each other's toes. +// +// NOTE: we're using the browser's "local storage" API via the +// 'localStorage' object to store both "local" (to the current Haddock +// page) and "global" (across all Haddock pages) configuration. Be +// aware of these two different uses of the term "local". +const localStoragePrefix: string = "local-details-config:"; + +// Local storage key for the current page. +function localStorageKey(): string { +  return localStoragePrefix + document.location.pathname; +} + +// Clear all local storage related to instance list configs. +function clearLocalStorage() { +  const keysToDelete: string[] = []; +  for (var i = 0; i < localStorage.length; ++i) { +    const key = localStorage.key(i); +    if (key !== null && key.startsWith(localStoragePrefix)) { +      keysToDelete.push(key); +    } +  } +  keysToDelete.forEach(key => { +    localStorage.removeItem(key); +  }); +} + +// Compute and save the set of instance list ids that aren't in the +// default state. +function storeLocalConfig() { +  if (!globalConfig.rememberToggles) return; +  const instanceListToggles: HTMLElement[] = +    // Restrict to 'details-toggle' elements for "instances" +    // *plural*. These are the toggles that control instance lists and +    // not the list of methods for individual instances. +    Array.prototype.slice.call(document.getElementsByClassName( +      'instances details-toggle details-toggle-control')); +  const nonDefaultInstanceListIds: string[] = []; +  instanceListToggles.forEach(toggle => { +    const id = getDataDetailsId(toggle); +    const details = document.getElementById(id) as HTMLDetailsElement; +    if (details.open != getDefaultOpenSetting()) { +      nonDefaultInstanceListIds.push(id); +    } +  }); + +  const json = JSON.stringify(nonDefaultInstanceListIds); +  try { +    // https://developer.mozilla.org/en-US/docs/Web/API/Storage/setItem#Exceptions. +    localStorage.setItem(localStorageKey(), json); +  } catch (e) {} +} + +function putInstanceListsInDefaultState() { +  switch (globalConfig.defaultInstanceState) { +    case DefaultState.Closed: _collapseAllInstances(true); break; +    case DefaultState.Open: _collapseAllInstances(false); break; +    default: break; +  } +} + +// Expand and collapse instance lists according to global and local +// config. +function restoreToggled() { +  loadGlobalConfig(); +  putInstanceListsInDefaultState(); +  if (!globalConfig.rememberToggles) { return; } +  const local = localStorage.getItem(localStorageKey()); +  if (!local) { return; } +  try { +    const nonDefaultInstanceListIds: string[] = JSON.parse(local); +    nonDefaultInstanceListIds.forEach(id => { +      const info = lookupDetailsRegistry(id); +      info.element.open = ! getDefaultOpenSetting(); +    }); +  } catch(e) { +    // Gracefully handle errors related to changed config format. +    if (e instanceof SyntaxError || e instanceof TypeError) { +      localStorage.removeItem(localStorageKey()); +    } else { +      throw e; +    } +  } +} + +// Handler for clicking on the "toggle" element that toggles the +// <details> element with id given by the 'data-details-id' property +// of the "toggle" element. +function onToggleClick(ev: MouseEvent) { +  ev.preventDefault(); +  const toggle = ev.currentTarget as HTMLElement; +  toggleDetails(toggle); +  storeLocalConfig(); +} + +// Set event handlers on elements responsible for expanding and +// collapsing <details> elements. +// +// This applies to all 'details-toggle's, not just to to top-level +// 'details-toggle's that control instance lists. +function initCollapseToggles() { +  const toggles: HTMLElement[] = Array.prototype.slice.call(document.getElementsByClassName('details-toggle')); +  toggles.forEach(toggle => { +    const id = getDataDetailsId(toggle); +    const info = lookupDetailsRegistry(id); +    info.toggles.push(toggle); +    toggle.addEventListener('click', onToggleClick); +    if (toggle.classList.contains('details-toggle-control')) { +      toggle.classList.add(info.element.open ? 'collapser' : 'expander'); +    } +  }); +} + +// Collapse or expand all instances. +function _collapseAllInstances(collapse: boolean) { +  const ilists = document.getElementsByClassName('subs instances'); +  [].forEach.call(ilists, function (ilist : Element) { +    const toggleType = collapse ? 'collapser' : 'expander'; +    const toggle = ilist.getElementsByClassName('instances ' + toggleType)[0]; +    if (toggle) { +      toggleDetails(toggle); +    } +  }); +} + +function collapseAllInstances() { +  _collapseAllInstances(true); +  storeLocalConfig(); +} + +function expandAllInstances() { +  _collapseAllInstances(false); +  storeLocalConfig(); +} + +export function init(showHide?: (action: () => void) => void) { +  gatherDetailsElements(); +  initCollapseToggles(); +  restoreToggled(); +  preact.render( +    <Preferences showHideTrigger={showHide || addPreferencesButton} />, +    document.body +  ); +} diff --git a/haddock-api/resources/html/js-src/init.ts b/haddock-api/resources/html/js-src/init.ts index 877874ae..1bfa8b3c 100644 --- a/haddock-api/resources/html/js-src/init.ts +++ b/haddock-api/resources/html/js-src/init.ts @@ -17,6 +17,6 @@ function onDomReady(callback: () => void) {  onDomReady(() => {    document.body.classList.add('js-enabled');    styleMenu.init(); -  detailsHelper.init();    quickJump.init(); -});
\ No newline at end of file +  detailsHelper.init(); +}); diff --git a/haddock-api/resources/html/js-src/style-menu.tsx b/haddock-api/resources/html/js-src/style-menu.tsx index bab840ca..2eb8344e 100644 --- a/haddock-api/resources/html/js-src/style-menu.tsx +++ b/haddock-api/resources/html/js-src/style-menu.tsx @@ -4,91 +4,14 @@ import {getCookie, setCookie, clearCookie} from "./cookies";  import preact = require("preact");  const { h, Component } = preact; -const rspace = /\s\s+/g, -    rtrim = /^\s+|\s+$/g; - -function spaced(s: string) { return (" " + s + " ").replace(rspace, " "); } -function trim(s: string)   { return s.replace(rtrim, ""); } - -function hasClass(elem: Element, value: string) { -  const className = spaced(elem.className || ""); -  return className.indexOf( " " + value + " " ) >= 0; -} - -function addClass(elem: Element, value: string) { -  const className = spaced(elem.className || ""); -  if ( className.indexOf( " " + value + " " ) < 0 ) { -    elem.className = trim(className + " " + value); -  } -} - -function removeClass(elem: Element, value: string) { -  let className = spaced(elem.className || ""); -  className = className.replace(" " + value + " ", " "); -  elem.className = trim(className); -} - -function toggleClass(elem: Element, valueOn: string, valueOff: string, bool?: boolean): boolean { -  if (bool == null) { bool = ! hasClass(elem, valueOn); } -  if (bool) { -    removeClass(elem, valueOff); -    addClass(elem, valueOn); -  } -  else { -    removeClass(elem, valueOn); -    addClass(elem, valueOff); -  } -  return bool; -} - -function makeClassToggle(valueOn: string, valueOff: string): (elem: Element, bool?: boolean) => boolean { -  return function(elem, bool) { -    return toggleClass(elem, valueOn, valueOff, bool); -  } -} - -const toggleShow = makeClassToggle("show", "hide"); +// Get all of the styles that are available  function styles(): HTMLLinkElement[] {    const es = Array.prototype.slice.call(document.getElementsByTagName("link"));    return es.filter((a: HTMLLinkElement) => a.rel.indexOf("style") != -1 && a.title);  } -class StyleMenuButton extends Component<any, any> { - -  render(props: { stys: string[] }) { -    function action() { -      styleMenu(); -      return false; -    }; - -    return <li><div id='style-menu-holder' onClick={action}> -      <a href='#'>Style ▾</a> -      <ul id='style-menu' class='hide'> -        {props.stys.map((sty) => { -              function action() { -                setActiveStyleSheet(sty); -                return false; -              }; - -              return <li><a href='#' onClick={action}>{sty}</a></li>; -        })} -      </ul> -    </div></li>; -  } - -} - -function addStyleMenu() { -  const stys = styles().map((s) => s.title); -  if (stys.length > 1) { -    const pageMenu = document.querySelector('#page-menu') as HTMLUListElement; -    const dummy = document.createElement('li'); -    pageMenu.appendChild(dummy); -    preact.render(<StyleMenuButton stys={stys} title="Style"/>, pageMenu, dummy); -  } -} - +// Set a style (including setting the cookie)  function setActiveStyleSheet(title: string) {    const as = styles();    let found: null | HTMLLinkElement = null; @@ -110,17 +33,103 @@ function setActiveStyleSheet(title: string) {    }  } +// Reset the style based on the cookie  function resetStyle() {    const s = getCookie("haddock-style");    if (s) setActiveStyleSheet(s);  } -function styleMenu(show?: boolean) { -  const m = document.getElementById('style-menu'); -  if (m) toggleShow(m, show); +class StylesButton extends Component<any, any> { +  render(props: { title: string, onClick: () => void }) { +    function onClick(e: Event) { +      e.preventDefault(); +      props.onClick(); +    } +    return <li><a href="#" onClick={onClick}>{props.title}</a></li>; +  }  } -export function init() { -  addStyleMenu(); +// Add the style menu button +function addStyleMenu(stys: string[], action: () => void) { +  if (stys.length > 1) { +    const pageMenu = document.querySelector('#page-menu') as HTMLUListElement; +    const dummy = document.createElement('li'); +    pageMenu.appendChild(dummy); +    preact.render(<StylesButton onClick={action} title="Styles"/>, pageMenu, dummy); +  } +} + +type StyleProps = { +  styles: string[] +  showHideTrigger: (action: () => void) => void +} + +type StyleState = { +  isVisible: boolean +} + +// Represents the full style dropdown +class Styles extends Component<StyleProps, StyleState> { + +  componentWillMount() { +    document.addEventListener('mousedown', this.hide.bind(this)); + +    document.addEventListener('keydown', (e) => { +      if (this.state.isVisible) { +        if (e.key === 'Escape') { +          this.hide(); +        } +      } +    }) +  } + +  hide() { +    this.setState({ isVisible: false }); +  } + +  show() { +    if (!this.state.isVisible) { +      this.setState({ isVisible: true }); +    } +  } + +  toggleVisibility() { +    if (this.state.isVisible) { +      this.hide(); +    } else { +      this.show(); +    } +  } + +  componentDidMount() { +    this.props.showHideTrigger(this.toggleVisibility.bind(this)); +  } + +  render(props: StyleProps, state: StyleState) { +    const stopPropagation = (e: Event) => { e.stopPropagation(); }; + +    return <div id="style" class={state.isVisible ? '' : 'hidden'}> +        <div id="style-menu" class="dropdown-menu" onMouseDown={stopPropagation}> +          { +            props.styles.map((sty) => +              <button type="button" +                      onClick={(e) => { this.hide(); setActiveStyleSheet(sty) }}> +                {sty} +              </button> +            ) +          } +        </div> +      </div>; +  } +} + + +export function init(showHide?: (action: () => void) => void) { +  const stys = styles().map((s) => s.title); +  const addStylesButton = (action: () => void) => addStyleMenu(stys, action)    resetStyle(); +  preact.render( +    <Styles showHideTrigger={showHide || addStylesButton} styles={stys} />, +    document.body +  );  } diff --git a/haddock-api/resources/html/package-lock.json b/haddock-api/resources/html/package-lock.json index b332921c..f09bde68 100644 --- a/haddock-api/resources/html/package-lock.json +++ b/haddock-api/resources/html/package-lock.json @@ -18,9 +18,9 @@        },        "dependencies": {          "acorn": { -          "version": "5.7.3", -          "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", -          "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", +          "version": "5.7.4", +          "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", +          "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==",            "dev": true          },          "source-map": { @@ -52,9 +52,9 @@        }      },      "acorn": { -      "version": "6.0.2", -      "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.2.tgz", -      "integrity": "sha512-GXmKIvbrN3TV7aVqAzVFaMW8F8wzVX7voEBRO3bDA64+EX37YSayggRJP5Xig6HYHBkWKpFg9W5gg6orklubhg==", +      "version": "6.4.1", +      "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", +      "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==",        "dev": true      },      "acorn-dynamic-import": { @@ -324,9 +324,9 @@        }      },      "async-each": { -      "version": "1.0.1", -      "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", -      "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", +      "version": "1.0.3", +      "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", +      "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==",        "dev": true      },      "async-settle": { @@ -429,15 +429,25 @@        "dev": true      },      "binary-extensions": { -      "version": "1.12.0", -      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz", -      "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==", +      "version": "1.13.1", +      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", +      "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",        "dev": true      }, +    "bindings": { +      "version": "1.5.0", +      "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", +      "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", +      "dev": true, +      "optional": true, +      "requires": { +        "file-uri-to-path": "1.0.0" +      } +    },      "bl": { -      "version": "1.2.2", -      "resolved": "http://registry.npmjs.org/bl/-/bl-1.2.2.tgz", -      "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", +      "version": "1.2.3", +      "resolved": "http://registry.npmjs.org/bl/-/bl-1.2.3.tgz", +      "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==",        "dev": true,        "requires": {          "readable-stream": "^2.3.5", @@ -718,9 +728,9 @@        }      },      "cached-path-relative": { -      "version": "1.0.1", -      "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.1.tgz", -      "integrity": "sha1-0JxLUoAKpMB44t2BqGmqyQ0uVOc=", +      "version": "1.0.2", +      "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.2.tgz", +      "integrity": "sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg==",        "dev": true      },      "camelcase": { @@ -730,24 +740,31 @@        "dev": true      },      "chokidar": { -      "version": "2.0.4", -      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", -      "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", +      "version": "2.1.8", +      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", +      "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",        "dev": true,        "requires": {          "anymatch": "^2.0.0", -        "async-each": "^1.0.0", -        "braces": "^2.3.0", -        "fsevents": "^1.2.2", +        "async-each": "^1.0.1", +        "braces": "^2.3.2", +        "fsevents": "^1.2.7",          "glob-parent": "^3.1.0", -        "inherits": "^2.0.1", +        "inherits": "^2.0.3",          "is-binary-path": "^1.0.0",          "is-glob": "^4.0.0", -        "lodash.debounce": "^4.0.8", -        "normalize-path": "^2.1.1", +        "normalize-path": "^3.0.0",          "path-is-absolute": "^1.0.0", -        "readdirp": "^2.0.0", -        "upath": "^1.0.5" +        "readdirp": "^2.2.1", +        "upath": "^1.1.1" +      }, +      "dependencies": { +        "normalize-path": { +          "version": "3.0.0", +          "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", +          "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", +          "dev": true +        }        }      },      "cipher-base": { @@ -1230,9 +1247,9 @@        },        "dependencies": {          "acorn": { -          "version": "5.7.3", -          "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", -          "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", +          "version": "5.7.4", +          "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", +          "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==",            "dev": true          }        } @@ -1286,9 +1303,9 @@        }      },      "elliptic": { -      "version": "6.4.1", -      "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", -      "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", +      "version": "6.5.3", +      "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", +      "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==",        "dev": true,        "requires": {          "bn.js": "^4.4.0", @@ -1560,6 +1577,13 @@          "time-stamp": "^1.0.0"        }      }, +    "file-uri-to-path": { +      "version": "1.0.0", +      "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", +      "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", +      "dev": true, +      "optional": true +    },      "fill-range": {        "version": "4.0.0",        "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -1686,14 +1710,15 @@        "dev": true      },      "fsevents": { -      "version": "1.2.4", -      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", -      "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", +      "version": "1.2.12", +      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.12.tgz", +      "integrity": "sha512-Ggd/Ktt7E7I8pxZRbGIs7vwqAPscSESMrCSkx2FtWeqmheJgCo2R74fTsZFCifr0VTPwqRpPv17+6b8Zp7th0Q==",        "dev": true,        "optional": true,        "requires": { -        "nan": "^2.9.2", -        "node-pre-gyp": "^0.10.0" +        "bindings": "^1.5.0", +        "nan": "^2.12.1", +        "node-pre-gyp": "*"        },        "dependencies": {          "abbrev": { @@ -1705,7 +1730,8 @@          "ansi-regex": {            "version": "2.1.1",            "bundled": true, -          "dev": true +          "dev": true, +          "optional": true          },          "aproba": {            "version": "1.2.0", @@ -1714,7 +1740,7 @@            "optional": true          },          "are-we-there-yet": { -          "version": "1.1.4", +          "version": "1.1.5",            "bundled": true,            "dev": true,            "optional": true, @@ -1726,19 +1752,21 @@          "balanced-match": {            "version": "1.0.0",            "bundled": true, -          "dev": true +          "dev": true, +          "optional": true          },          "brace-expansion": {            "version": "1.1.11",            "bundled": true,            "dev": true, +          "optional": true,            "requires": {              "balanced-match": "^1.0.0",              "concat-map": "0.0.1"            }          },          "chownr": { -          "version": "1.0.1", +          "version": "1.1.4",            "bundled": true,            "dev": true,            "optional": true @@ -1746,17 +1774,20 @@          "code-point-at": {            "version": "1.1.0",            "bundled": true, -          "dev": true +          "dev": true, +          "optional": true          },          "concat-map": {            "version": "0.0.1",            "bundled": true, -          "dev": true +          "dev": true, +          "optional": true          },          "console-control-strings": {            "version": "1.1.0",            "bundled": true, -          "dev": true +          "dev": true, +          "optional": true          },          "core-util-is": {            "version": "1.0.2", @@ -1765,16 +1796,16 @@            "optional": true          },          "debug": { -          "version": "2.6.9", +          "version": "3.2.6",            "bundled": true,            "dev": true,            "optional": true,            "requires": { -            "ms": "2.0.0" +            "ms": "^2.1.1"            }          },          "deep-extend": { -          "version": "0.5.1", +          "version": "0.6.0",            "bundled": true,            "dev": true,            "optional": true @@ -1792,12 +1823,12 @@            "optional": true          },          "fs-minipass": { -          "version": "1.2.5", +          "version": "1.2.7",            "bundled": true,            "dev": true,            "optional": true,            "requires": { -            "minipass": "^2.2.1" +            "minipass": "^2.6.0"            }          },          "fs.realpath": { @@ -1823,7 +1854,7 @@            }          },          "glob": { -          "version": "7.1.2", +          "version": "7.1.6",            "bundled": true,            "dev": true,            "optional": true, @@ -1843,16 +1874,16 @@            "optional": true          },          "iconv-lite": { -          "version": "0.4.21", +          "version": "0.4.24",            "bundled": true,            "dev": true,            "optional": true,            "requires": { -            "safer-buffer": "^2.1.0" +            "safer-buffer": ">= 2.1.2 < 3"            }          },          "ignore-walk": { -          "version": "3.0.1", +          "version": "3.0.3",            "bundled": true,            "dev": true,            "optional": true, @@ -1871,12 +1902,7 @@            }          },          "inherits": { -          "version": "2.0.3", -          "bundled": true, -          "dev": true -        }, -        "ini": { -          "version": "1.3.5", +          "version": "2.0.4",            "bundled": true,            "dev": true,            "optional": true @@ -1885,6 +1911,7 @@            "version": "1.0.0",            "bundled": true,            "dev": true, +          "optional": true,            "requires": {              "number-is-nan": "^1.0.0"            } @@ -1899,78 +1926,82 @@            "version": "3.0.4",            "bundled": true,            "dev": true, +          "optional": true,            "requires": {              "brace-expansion": "^1.1.7"            }          },          "minimist": { -          "version": "0.0.8", +          "version": "1.2.5",            "bundled": true, -          "dev": true +          "dev": true, +          "optional": true          },          "minipass": { -          "version": "2.2.4", +          "version": "2.9.0",            "bundled": true,            "dev": true, +          "optional": true,            "requires": { -            "safe-buffer": "^5.1.1", +            "safe-buffer": "^5.1.2",              "yallist": "^3.0.0"            }          },          "minizlib": { -          "version": "1.1.0", +          "version": "1.3.3",            "bundled": true,            "dev": true,            "optional": true,            "requires": { -            "minipass": "^2.2.1" +            "minipass": "^2.9.0"            }          },          "mkdirp": { -          "version": "0.5.1", +          "version": "0.5.3",            "bundled": true,            "dev": true, +          "optional": true,            "requires": { -            "minimist": "0.0.8" +            "minimist": "^1.2.5"            }          },          "ms": { -          "version": "2.0.0", +          "version": "2.1.2",            "bundled": true,            "dev": true,            "optional": true          },          "needle": { -          "version": "2.2.0", +          "version": "2.3.3",            "bundled": true,            "dev": true,            "optional": true,            "requires": { -            "debug": "^2.1.2", +            "debug": "^3.2.6",              "iconv-lite": "^0.4.4",              "sax": "^1.2.4"            }          },          "node-pre-gyp": { -          "version": "0.10.0", +          "version": "0.14.0",            "bundled": true,            "dev": true,            "optional": true,            "requires": {              "detect-libc": "^1.0.2",              "mkdirp": "^0.5.1", -            "needle": "^2.2.0", +            "needle": "^2.2.1",              "nopt": "^4.0.1",              "npm-packlist": "^1.1.6",              "npmlog": "^4.0.2", -            "rc": "^1.1.7", +            "rc": "^1.2.7",              "rimraf": "^2.6.1",              "semver": "^5.3.0", -            "tar": "^4" +            "tar": "^4.4.2"            }          },          "nopt": { -          "version": "4.0.1", +          "version": "4.0.3",            "bundled": true,            "dev": true,            "optional": true, @@ -1980,19 +2011,29 @@            }          },          "npm-bundled": { -          "version": "1.0.3", +          "version": "1.1.1", +          "bundled": true, +          "dev": true, +          "optional": true, +          "requires": { +            "npm-normalize-package-bin": "^1.0.1" +          } +        }, +        "npm-normalize-package-bin": { +          "version": "1.0.1",            "bundled": true,            "dev": true,            "optional": true          },          "npm-packlist": { -          "version": "1.1.10", +          "version": "1.4.8",            "bundled": true,            "dev": true,            "optional": true,            "requires": {              "ignore-walk": "^3.0.1", -            "npm-bundled": "^1.0.1" +            "npm-bundled": "^1.0.1", +            "npm-normalize-package-bin": "^1.0.1"            }          },          "npmlog": { @@ -2010,7 +2051,8 @@          "number-is-nan": {            "version": "1.0.1",            "bundled": true, -          "dev": true +          "dev": true, +          "optional": true          },          "object-assign": {            "version": "4.1.1", @@ -2022,6 +2064,7 @@            "version": "1.4.0",            "bundled": true,            "dev": true, +          "optional": true,            "requires": {              "wrappy": "1"            } @@ -2055,33 +2098,25 @@            "optional": true          },          "process-nextick-args": { -          "version": "2.0.0", +          "version": "2.0.1",            "bundled": true,            "dev": true,            "optional": true          },          "rc": { -          "version": "1.2.7", +          "version": "1.2.8",            "bundled": true,            "dev": true,            "optional": true,            "requires": { -            "deep-extend": "^0.5.1", +            "deep-extend": "^0.6.0",              "ini": "~1.3.0",              "minimist": "^1.2.0",              "strip-json-comments": "~2.0.1" -          }, -          "dependencies": { -            "minimist": { -              "version": "1.2.0", -              "bundled": true, -              "dev": true, -              "optional": true -            }            }          },          "readable-stream": { -          "version": "2.3.6", +          "version": "2.3.7",            "bundled": true,            "dev": true,            "optional": true, @@ -2096,18 +2131,19 @@            }          },          "rimraf": { -          "version": "2.6.2", +          "version": "2.7.1",            "bundled": true,            "dev": true,            "optional": true,            "requires": { -            "glob": "^7.0.5" +            "glob": "^7.1.3"            }          },          "safe-buffer": { -          "version": "5.1.1", +          "version": "5.1.2",            "bundled": true, -          "dev": true +          "dev": true, +          "optional": true          },          "safer-buffer": {            "version": "2.1.2", @@ -2122,7 +2158,7 @@            "optional": true          },          "semver": { -          "version": "5.5.0", +          "version": "5.7.1",            "bundled": true,            "dev": true,            "optional": true @@ -2143,6 +2179,7 @@            "version": "1.0.2",            "bundled": true,            "dev": true, +          "optional": true,            "requires": {              "code-point-at": "^1.0.0",              "is-fullwidth-code-point": "^1.0.0", @@ -2162,6 +2199,7 @@            "version": "3.0.1",            "bundled": true,            "dev": true, +          "optional": true,            "requires": {              "ansi-regex": "^2.0.0"            } @@ -2173,18 +2211,18 @@            "optional": true          },          "tar": { -          "version": "4.4.1", +          "version": "4.4.13",            "bundled": true,            "dev": true,            "optional": true,            "requires": { -            "chownr": "^1.0.1", +            "chownr": "^1.1.1",              "fs-minipass": "^1.2.5", -            "minipass": "^2.2.4", -            "minizlib": "^1.1.0", +            "minipass": "^2.8.6", +            "minizlib": "^1.2.1",              "mkdirp": "^0.5.0", -            "safe-buffer": "^5.1.1", -            "yallist": "^3.0.2" +            "safe-buffer": "^5.1.2", +            "yallist": "^3.0.3"            }          },          "util-deprecate": { @@ -2194,23 +2232,25 @@            "optional": true          },          "wide-align": { -          "version": "1.1.2", +          "version": "1.1.3",            "bundled": true,            "dev": true,            "optional": true,            "requires": { -            "string-width": "^1.0.2" +            "string-width": "^1.0.2 || 2"            }          },          "wrappy": {            "version": "1.0.2",            "bundled": true, -          "dev": true +          "dev": true, +          "optional": true          },          "yallist": { -          "version": "3.0.2", +          "version": "3.1.1",            "bundled": true, -          "dev": true +          "dev": true, +          "optional": true          }        }      }, @@ -2297,13 +2337,15 @@        }      },      "glob-watcher": { -      "version": "5.0.1", -      "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.1.tgz", -      "integrity": "sha512-fK92r2COMC199WCyGUblrZKhjra3cyVMDiypDdqg1vsSDmexnbYivK1kNR4QItiNXLKmGlqan469ks67RtNa2g==", +      "version": "5.0.3", +      "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.3.tgz", +      "integrity": "sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg==",        "dev": true,        "requires": { +        "anymatch": "^2.0.0",          "async-done": "^1.2.0",          "chokidar": "^2.0.0", +        "is-negated-glob": "^1.0.0",          "just-debounce": "^1.0.0",          "object.defaults": "^1.1.0"        } @@ -2419,9 +2461,9 @@        },        "dependencies": {          "acorn": { -          "version": "5.7.3", -          "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", -          "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", +          "version": "5.7.4", +          "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", +          "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==",            "dev": true          },          "source-map": { @@ -2532,9 +2574,9 @@        }      },      "hash.js": { -      "version": "1.1.5", -      "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz", -      "integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==", +      "version": "1.1.7", +      "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", +      "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",        "dev": true,        "requires": {          "inherits": "^2.0.3", @@ -2608,9 +2650,9 @@        "dev": true      },      "ini": { -      "version": "1.3.5", -      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", -      "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", +      "version": "1.3.7", +      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", +      "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==",        "dev": true      },      "inline-source-map": { @@ -2787,9 +2829,9 @@        }      },      "is-glob": { -      "version": "4.0.0", -      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", -      "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", +      "version": "4.0.1", +      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", +      "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",        "dev": true,        "requires": {          "is-extglob": "^2.1.1" @@ -2918,9 +2960,9 @@        "dev": true      },      "kind-of": { -      "version": "6.0.2", -      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", -      "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", +      "version": "6.0.3", +      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", +      "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",        "dev": true      },      "labeled-stream-splicer": { @@ -3009,15 +3051,9 @@        }      },      "lodash": { -      "version": "4.17.11", -      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", -      "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", -      "dev": true -    }, -    "lodash.debounce": { -      "version": "4.0.8", -      "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", -      "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", +      "version": "4.17.20", +      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", +      "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",        "dev": true      },      "lodash.memoize": { @@ -3198,15 +3234,15 @@        }      },      "minimist": { -      "version": "1.2.0", -      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", -      "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", +      "version": "1.2.5", +      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", +      "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",        "dev": true      },      "mixin-deep": { -      "version": "1.3.1", -      "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", -      "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", +      "version": "1.3.2", +      "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", +      "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",        "dev": true,        "requires": {          "for-in": "^1.0.2", @@ -3254,9 +3290,9 @@        "dev": true      },      "nan": { -      "version": "2.11.1", -      "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz", -      "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==", +      "version": "2.14.0", +      "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", +      "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==",        "dev": true,        "optional": true      }, @@ -3759,7 +3795,7 @@      },      "readable-stream": {        "version": "2.3.6", -      "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", +      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",        "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",        "dev": true,        "requires": { @@ -3974,9 +4010,9 @@        "dev": true      },      "set-value": { -      "version": "2.0.0", -      "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", -      "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", +      "version": "2.0.1", +      "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", +      "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",        "dev": true,        "requires": {          "extend-shallow": "^2.0.1", @@ -4682,38 +4718,15 @@        "dev": true      },      "union-value": { -      "version": "1.0.0", -      "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", -      "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", +      "version": "1.0.1", +      "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", +      "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",        "dev": true,        "requires": {          "arr-union": "^3.1.0",          "get-value": "^2.0.6",          "is-extendable": "^0.1.1", -        "set-value": "^0.4.3" -      }, -      "dependencies": { -        "extend-shallow": { -          "version": "2.0.1", -          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", -          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", -          "dev": true, -          "requires": { -            "is-extendable": "^0.1.0" -          } -        }, -        "set-value": { -          "version": "0.4.3", -          "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", -          "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", -          "dev": true, -          "requires": { -            "extend-shallow": "^2.0.1", -            "is-extendable": "^0.1.1", -            "is-plain-object": "^2.0.1", -            "to-object-path": "^0.3.0" -          } -        } +        "set-value": "^2.0.1"        }      },      "unique-stream": { @@ -4784,9 +4797,9 @@        }      },      "upath": { -      "version": "1.1.0", -      "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", -      "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", +      "version": "1.2.0", +      "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", +      "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==",        "dev": true      },      "urix": { diff --git a/haddock-api/resources/html/quick-jump.css b/haddock-api/resources/html/quick-jump.css index 468d8036..d656f51c 100644 --- a/haddock-api/resources/html/quick-jump.css +++ b/haddock-api/resources/html/quick-jump.css @@ -1,3 +1,11 @@ +/* @group Fundamentals */ + +.hidden { +  display: none; +} + +/* @end */ +  /* @group Search box layout */  #search { @@ -11,8 +19,10 @@    overflow-y: auto;  } -#search.hidden { -  display: none; +@media only screen and (max-width: 999px) { +  #search { +    top: 5.7em; +  }  }  #search-form, #search-results { @@ -43,6 +53,8 @@    box-sizing: border-box;    border: 0.05em solid #b2d5fb;    background: #e8f3ff; +  max-height: 80%; +  overflow: scroll;  }  #search-form input + #search-results { @@ -162,3 +174,49 @@  }  /* @end */ + +/* @group Dropdown menus */ + +/* Based on #search styling above. */ + +.dropdown-menu { +  position: fixed; +  /* Not robust to window size changes. */ +  top: 3.2em; +  right: 0; +  /* To display on top of synopsis menu on right side. */ +  z-index: 1000; +  border: 0.05em solid #b2d5fb; +  background: #e8f3ff; +} + +@media only screen and (max-width: 999px) { +  .dropdown-menu { +    top: 5.7em; +  } +} + +.dropdown-menu * { +  margin: 0.1em; +} + +.dropdown-menu button { +  border: 1px #5E5184 solid; +  border-radius: 3px; +  background: #5E5184; +  padding: 3px; +  color: #f4f4f4; +  min-width: 6em; +} + +.dropdown-menu button:hover { +  color: #5E5184; +  background: #f4f4f4; +} + +.dropdown-menu button:active { +  color: #f4f4f4; +  background: #5E5184; +} + +/* @end */ diff --git a/haddock-api/src/Haddock.hs b/haddock-api/src/Haddock.hs index 8bf932df..2b6e2d57 100644 --- a/haddock-api/src/Haddock.hs +++ b/haddock-api/src/Haddock.hs @@ -42,6 +42,8 @@ import Haddock.Utils  import Haddock.GhcUtils (modifySessionDynFlags, setOutputDir)  import Control.Monad hiding (forM_) +import Control.Monad.IO.Class (MonadIO(..)) +import Data.Bifunctor (second)  import Data.Foldable (forM_, foldl')  import Data.Traversable (for)  import Data.List (isPrefixOf) @@ -53,9 +55,9 @@ import Data.Version (makeVersion)  import qualified Data.Map as Map  import System.IO  import System.Exit +import System.FilePath  #ifdef IN_GHC_TREE -import System.FilePath  import System.Environment (getExecutablePath)  #else  import qualified GHC.Paths as GhcPaths @@ -67,12 +69,12 @@ import Text.ParserCombinators.ReadP (readP_to_S)  import GHC hiding (verbosity)  import GHC.Settings.Config  import GHC.Driver.Session hiding (projectVersion, verbosity) +import GHC.Utils.Outputable (defaultUserStyle, withPprStyle)  import GHC.Driver.Env  import GHC.Utils.Error  import GHC.Unit  import GHC.Utils.Panic (handleGhcException)  import GHC.Data.FastString -import qualified GHC.Runtime.Loader  --------------------------------------------------------------------------------  -- * Exception handling @@ -188,7 +190,7 @@ haddockWithGhc ghc args = handleTopExceptions $ do      forM_ (optShowInterfaceFile flags) $ \path -> liftIO $ do        mIfaceFile <- readInterfaceFiles freshNameCache [(("", Nothing), path)] noChecks        forM_ mIfaceFile $ \(_, ifaceFile) -> do -        putMsg dflags (renderJson (jsonInterfaceFile ifaceFile)) +        logOutput dflags $ withPprStyle defaultUserStyle (renderJson (jsonInterfaceFile ifaceFile))      if not (null files) then do        (packages, ifaces, homeLinks) <- readPackagesAndProcessModules flags files @@ -430,7 +432,7 @@ render dflags unit_state flags sinceQual qual ifaces installedIfaces extSrcMap =    when (Flag_HyperlinkedSource `elem` flags && not (null ifaces)) $ do      withTiming dflags' "ppHyperlinkedSource" (const ()) $ do        _ <- {-# SCC ppHyperlinkedSource #-} -           ppHyperlinkedSource odir libDir opt_source_css pretty srcMap ifaces +           ppHyperlinkedSource (verbosity flags) odir libDir opt_source_css pretty srcMap ifaces        return () @@ -477,10 +479,7 @@ withGhc' libDir needHieFiles flags ghcActs = runGhc (Just libDir) $ do    -- that may need to be re-linked: Haddock doesn't do any    -- dynamic or static linking at all!    _ <- setSessionDynFlags dynflags'' -  hsc_env <- GHC.getSession -  hsc_env'' <- liftIO (GHC.Runtime.Loader.initializePlugins hsc_env) -  _ <- GHC.setSession hsc_env'' -  ghcActs (hsc_dflags hsc_env'') +  ghcActs dynflags''    where      -- ignore sublists of flags that start with "+RTS" and end in "-RTS" @@ -696,7 +695,7 @@ getPrologue dflags flags =        h <- openFile filename ReadMode        hSetEncoding h utf8        str <- hGetContents h -- semi-closes the handle -      return . Just $! parseParas dflags Nothing str +      return . Just $! second (fmap rdrName) $ parseParas dflags Nothing str      _ -> throwE "multiple -p/--prologue options" diff --git a/haddock-api/src/Haddock/Backends/Hoogle.hs b/haddock-api/src/Haddock/Backends/Hoogle.hs index 520b51f3..3bf12477 100644 --- a/haddock-api/src/Haddock/Backends/Hoogle.hs +++ b/haddock-api/src/Haddock/Backends/Hoogle.hs @@ -41,7 +41,6 @@ import Data.Version  import System.Directory  import System.FilePath -  prefix :: [String]  prefix = ["-- Hoogle documentation, generated by Haddock"           ,"-- See Hoogle, http://www.haskell.org/hoogle/" @@ -224,7 +223,7 @@ ppSynonym dflags x = [out dflags x]  ppData :: DynFlags -> TyClDecl GhcRn -> [(Name, DocForDecl Name)] -> [String]  ppData dflags decl@(DataDecl { tcdDataDefn = defn }) subdocs      = showData decl{ tcdDataDefn = defn { dd_cons=[],dd_derivs=noLoc [] }} : -      concatMap (ppCtor dflags decl subdocs . unL) (dd_cons defn) +      concatMap (ppCtor dflags decl subdocs . unLoc) (dd_cons defn)      where          -- GHC gives out "data Bar =", we want to delete the equals. @@ -316,7 +315,7 @@ docWith dflags header 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) +   getDoc = maybe [] (return . fst) (lookup (unLoc n) subdocs)  data Tag = TagL Char [Tags] | TagP Tags | TagPre Tags | TagInline String Tags | Str String             deriving Show @@ -343,7 +342,7 @@ markupTag dflags = Markup {    markupString               = str,    markupAppend               = (++),    markupIdentifier           = box (TagInline "a") . str . out dflags, -  markupIdentifierUnchecked  = box (TagInline "a") . str . out dflags . snd, +  markupIdentifierUnchecked  = box (TagInline "a") . str . showWrapped (out dflags . snd),    markupModule               = box (TagInline "a") . str,    markupWarning              = box (TagInline "i"),    markupEmphasis             = box (TagInline "i"), diff --git a/haddock-api/src/Haddock/Backends/Hyperlinker.hs b/haddock-api/src/Haddock/Backends/Hyperlinker.hs index 2ae4dcdb..8ecc185b 100644 --- a/haddock-api/src/Haddock/Backends/Hyperlinker.hs +++ b/haddock-api/src/Haddock/Backends/Hyperlinker.hs @@ -7,7 +7,7 @@ module Haddock.Backends.Hyperlinker  import Haddock.Types -import Haddock.Utils (writeUtf8File) +import Haddock.Utils (writeUtf8File, out, verbose, Verbosity)  import Haddock.Backends.Hyperlinker.Renderer  import Haddock.Backends.Hyperlinker.Parser  import Haddock.Backends.Hyperlinker.Types @@ -20,6 +20,7 @@ import System.FilePath  import GHC.Iface.Ext.Types  import GHC.Iface.Ext.Binary ( readHieFile, hie_file_result, NameCacheUpdater(..)) +import GHC.Types.SrcLoc     ( realSrcLocSpan, mkRealSrcLoc )  import Data.Map as M  import GHC.Data.FastString     ( mkFastString )  import GHC.Unit.Module         ( Module, moduleName ) @@ -32,27 +33,28 @@ import GHC.Types.Unique.Supply ( mkSplitUniqSupply )  -- Note that list of interfaces should also contain interfaces normally hidden  -- when generating documentation. Otherwise this could lead to dead links in  -- produced source. -ppHyperlinkedSource :: FilePath -- ^ Output directory +ppHyperlinkedSource :: Verbosity +                    -> FilePath -- ^ Output directory                      -> FilePath -- ^ Resource directory                      -> Maybe FilePath -- ^ Custom CSS file path                      -> Bool -- ^ Flag indicating whether to pretty-print HTML                      -> M.Map Module SrcPath -- ^ Paths to sources                      -> [Interface] -- ^ Interfaces for which we create source                      -> IO () -ppHyperlinkedSource outdir libdir mstyle pretty srcs' ifaces = do +ppHyperlinkedSource verbosity outdir libdir mstyle pretty srcs' ifaces = do      createDirectoryIfMissing True srcdir      let cssFile = fromMaybe (defaultCssFile libdir) mstyle      copyFile cssFile $ srcdir </> srcCssFile      copyFile (libdir </> "html" </> highlightScript) $          srcdir </> highlightScript -    mapM_ (ppHyperlinkedModuleSource srcdir pretty srcs) ifaces +    mapM_ (ppHyperlinkedModuleSource verbosity srcdir pretty srcs) ifaces    where      srcdir = outdir </> hypSrcDir      srcs = (srcs', M.mapKeys moduleName srcs')  -- | Generate hyperlinked source for particular interface. -ppHyperlinkedModuleSource :: FilePath -> Bool -> SrcMaps -> Interface -> IO () -ppHyperlinkedModuleSource srcdir pretty srcs iface = case ifaceHieFile iface of +ppHyperlinkedModuleSource :: Verbosity -> FilePath -> Bool -> SrcMaps -> Interface -> IO () +ppHyperlinkedModuleSource verbosity srcdir pretty srcs iface = case ifaceHieFile iface of      Just hfp -> do          -- Parse the GHC-produced HIE file          u <- mkSplitUniqSupply 'a' @@ -66,25 +68,33 @@ ppHyperlinkedModuleSource srcdir pretty srcs iface = case ifaceHieFile iface of                   <$> (readHieFile ncu hfp)          -- Get the AST and tokens corresponding to the source file we want -        let mast | M.size asts == 1 = snd <$> M.lookupMin asts +        let fileFs = mkFastString file +            mast | M.size asts == 1 = snd <$> M.lookupMin asts                   | otherwise        = M.lookup (HiePath (mkFastString file)) asts              tokens = parse df file rawSrc +            ast = fromMaybe (emptyHieAst fileFs) mast +            fullAst = recoverFullIfaceTypes df types ast + +        -- Warn if we didn't find an AST, but there were still ASTs +        if M.null asts +          then pure () +          else out verbosity verbose $ unwords [ "couldn't find ast for" +                                               , file, show (M.keys asts) ]          -- Produce and write out the hyperlinked sources -        case mast of -          Just ast -> -              let fullAst = recoverFullIfaceTypes df types ast -              in writeUtf8File path . renderToString pretty . render' fullAst $ tokens -          Nothing -            | M.size asts == 0 -> return () -            | otherwise -> error $ unwords [ "couldn't find ast for" -                                           , file, show (M.keys asts) ] +        writeUtf8File path . renderToString pretty . render' fullAst $ tokens      Nothing -> return ()    where      df = ifaceDynFlags iface      render' = render (Just srcCssFile) (Just highlightScript) srcs      path = srcdir </> hypSrcModuleFile (ifaceMod iface) +    emptyHieAst fileFs = Node +      { nodeSpan = realSrcLocSpan (mkRealSrcLoc fileFs 1 0) +      , nodeChildren = [] +      , sourcedNodeInfo = SourcedNodeInfo mempty +      } +  -- | Name of CSS file in output directory.  srcCssFile :: FilePath  srcCssFile = "style.css" diff --git a/haddock-api/src/Haddock/Backends/Hyperlinker/Parser.hs b/haddock-api/src/Haddock/Backends/Hyperlinker/Parser.hs index 5c2bdd4e..52d73265 100644 --- a/haddock-api/src/Haddock/Backends/Hyperlinker/Parser.hs +++ b/haddock-api/src/Haddock/Backends/Hyperlinker/Parser.hs @@ -3,9 +3,9 @@  {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}  module Haddock.Backends.Hyperlinker.Parser (parse) where +import Control.Monad.Trans.Maybe +import Control.Monad.Trans.Class  import Control.Applicative ( Alternative(..) ) -import Control.Monad.Trans.Maybe ( MaybeT(..) ) -import Control.Monad.Trans.Class ( MonadTrans(lift) )  import Data.List           ( isPrefixOf, isSuffixOf )  import qualified Data.ByteString as BS @@ -24,7 +24,6 @@ import GHC.Utils.Panic      ( panic )  import GHC.Driver.Ppr       ( showSDoc )  import GHC.Types.SrcLoc  import GHC.Data.StringBuffer ( StringBuffer, atEnd ) -import GHC.Unit              ( homeUnitId )  import Haddock.Backends.Hyperlinker.Types as T  import Haddock.GhcUtils diff --git a/haddock-api/src/Haddock/Backends/Hyperlinker/Utils.hs b/haddock-api/src/Haddock/Backends/Hyperlinker/Utils.hs index 5daa5522..5c3bddef 100644 --- a/haddock-api/src/Haddock/Backends/Hyperlinker/Utils.hs +++ b/haddock-api/src/Haddock/Backends/Hyperlinker/Utils.hs @@ -102,7 +102,7 @@ type PrintedType = String  -- >       hieAst  --  -- However, this is very inefficient (both in time and space) because the --- mutliple calls to 'recoverFullType' don't share intermediate results. This +-- multiple calls to 'recoverFullType' don't share intermediate results. This  -- function fixes that.  recoverFullIfaceTypes    :: DynFlags diff --git a/haddock-api/src/Haddock/Backends/LaTeX.hs b/haddock-api/src/Haddock/Backends/LaTeX.hs index 03c1209a..5b27847e 100644 --- a/haddock-api/src/Haddock/Backends/LaTeX.hs +++ b/haddock-api/src/Haddock/Backends/LaTeX.hs @@ -39,7 +39,8 @@ import System.FilePath  import Data.Char  import Control.Monad  import Data.Maybe -import Data.List (sort) +import Data.List            ( sort ) +import Data.Void            ( absurd )  import Prelude hiding ((<>))  import Haddock.Doc (combineDocumentation) @@ -104,6 +105,10 @@ haddockSty = "haddock.sty"  type LaTeX = Pretty.Doc +-- | Default way of rendering a 'LaTeX'. The width is 90 by default (since 100 +-- often overflows the line). +latex2String :: LaTeX -> String +latex2String = fullRender (PageMode True) 90 1 txtPrinter ""  ppLaTeXTop     :: String @@ -157,7 +162,7 @@ ppLaTeXModule _title odir iface = do          text "\\haddockbeginheader",          verb $ vcat [             text "module" <+> text mdl_str <+> lparen, -           text "    " <> fsep (punctuate (text ", ") $ +           text "    " <> fsep (punctuate (char ',') $                                 map exportListItem $                                 filter forSummary exports),             text "  ) where" @@ -288,7 +293,7 @@ ppDecl :: LHsDecl DocNameI                         -- ^ decl to print         -> LaTeX  ppDecl decl pats (doc, fnArgsDoc) instances subdocs _fxts = case unLoc decl of -  TyClD _ d@FamDecl {}         -> ppFamDecl doc instances d unicode +  TyClD _ d@FamDecl {}         -> ppFamDecl False doc instances d unicode    TyClD _ d@DataDecl {}        -> ppDataDecl pats instances subdocs (Just doc) d unicode    TyClD _ d@SynDecl {}         -> ppTySyn (doc, fnArgsDoc) d unicode  -- Family instances happen via FamInst now @@ -296,7 +301,7 @@ ppDecl decl pats (doc, fnArgsDoc) instances subdocs _fxts = case unLoc decl of  --    | Just _  <- tcdTyPats d    -> ppTyInst False loc doc d unicode  -- Family instances happen via FamInst now    TyClD _ d@ClassDecl{}          -> ppClassDecl instances doc subdocs d unicode -  SigD _ (TypeSig _ lnames ty)   -> ppFunSig (doc, fnArgsDoc) (map unLoc lnames) (dropWildCards ty) unicode +  SigD _ (TypeSig _ lnames ty)   -> ppFunSig Nothing (doc, fnArgsDoc) (map unLoc lnames) (dropWildCards ty) unicode    SigD _ (PatSynSig _ lnames ty) -> ppLPatSig (doc, fnArgsDoc) (map unLoc lnames) ty unicode    ForD _ d                       -> ppFor (doc, fnArgsDoc) d unicode    InstD _ _                      -> empty @@ -308,7 +313,7 @@ ppDecl decl pats (doc, fnArgsDoc) instances subdocs _fxts = case unLoc decl of  ppFor :: DocForDecl DocName -> ForeignDecl DocNameI -> Bool -> LaTeX  ppFor doc (ForeignImport _ (L _ name) typ _) unicode = -  ppFunSig doc [name] typ unicode +  ppFunSig Nothing doc [name] typ unicode  ppFor _ _ _ = error "ppFor error in Haddock.Backends.LaTeX"  --  error "foreign declarations are currently not supported by --latex" @@ -318,13 +323,14 @@ ppFor _ _ _ = error "ppFor error in Haddock.Backends.LaTeX"  -------------------------------------------------------------------------------  -- | Pretty-print a data\/type family declaration -ppFamDecl :: Documentation DocName    -- ^ this decl's docs +ppFamDecl :: Bool                     -- ^ is the family associated? +          -> Documentation DocName    -- ^ this decl's docs            -> [DocInstance DocNameI]   -- ^ relevant instances            -> TyClDecl DocNameI        -- ^ family to print            -> Bool                     -- ^ unicode            -> LaTeX -ppFamDecl doc instances decl unicode = -  declWithDoc (ppFamHeader (tcdFam decl) unicode <+> whereBit) +ppFamDecl associated doc instances decl unicode = +  declWithDoc (ppFamHeader (tcdFam decl) unicode associated <+> whereBit)                (if null body then Nothing else Just (vcat body))    $$ instancesBit    where @@ -336,6 +342,7 @@ ppFamDecl doc instances decl unicode =      familyEqns        | FamilyDecl { fdInfo = ClosedTypeFamily (Just eqns) } <- tcdFam decl +      , not (null eqns)        = Just (text "\\haddockbeginargs" $$                vcat [ decltt (ppFamDeclEqn eqn) <+> nl | L _ eqn <- eqns ] $$                text "\\end{tabulary}\\par") @@ -355,21 +362,25 @@ ppFamDecl doc instances decl unicode =  -- | Print the LHS of a type\/data family declaration.  ppFamHeader :: FamilyDecl DocNameI  -- ^ family header to print -              -> Bool                 -- ^ unicode -              -> LaTeX +            -> Bool                 -- ^ unicode +            -> Bool                 -- ^ is the family associated? +            -> LaTeX  ppFamHeader (FamilyDecl { fdLName = L _ name                          , fdTyVars = tvs                          , fdInfo = info                          , fdResultSig = L _ result                          , fdInjectivityAnn = injectivity }) -              unicode = -  leader <+> keyword "family" <+> famName <+> famSig <+> injAnn +              unicode associated = +  famly leader <+> famName <+> famSig <+> injAnn    where      leader = case info of        OpenTypeFamily     -> keyword "type"        ClosedTypeFamily _ -> keyword "type"        DataFamily         -> keyword "data" +    famly | associated = id +          | otherwise = (<+> keyword "family") +      famName = ppAppDocNameTyVarBndrs unicode name (hsq_explicit tvs)      famSig = case result of @@ -411,17 +422,23 @@ ppTySyn _ _ _ = error "declaration not supported by ppTySyn"  ------------------------------------------------------------------------------- -ppFunSig :: DocForDecl DocName -> [DocName] -> LHsSigType DocNameI -         -> Bool -> LaTeX -ppFunSig doc docnames (L _ typ) unicode = +ppFunSig +  :: Maybe LaTeX         -- ^ a prefix to put right before the signature +  -> DocForDecl DocName  -- ^ documentation +  -> [DocName]           -- ^ pattern names in the pattern signature +  -> LHsSigType DocNameI -- ^ type of the pattern synonym +  -> Bool                -- ^ unicode +  -> LaTeX +ppFunSig leader doc docnames (L _ typ) unicode =    ppTypeOrFunSig typ doc -    ( ppTypeSig names typ False -    , hsep . punctuate comma $ map ppSymName names +    ( lead $ ppTypeSig names typ False +    , lead $ hsep . punctuate comma $ map ppSymName names      , dcolon unicode      )      unicode   where     names = map getName docnames +   lead = maybe id (<+>) leader  -- | Pretty-print a pattern synonym  ppLPatSig :: DocForDecl DocName  -- ^ documentation @@ -430,15 +447,7 @@ ppLPatSig :: DocForDecl DocName  -- ^ documentation            -> Bool                -- ^ unicode            -> LaTeX  ppLPatSig doc docnames ty unicode -  = ppTypeOrFunSig typ doc -      ( keyword "pattern" <+> ppTypeSig names typ False -      , keyword "pattern" <+> (hsep . punctuate comma $ map ppSymName names) -      , dcolon unicode -      ) -      unicode -  where -    typ = unLoc ty -    names = map getName docnames +  = ppFunSig (Just (keyword "pattern")) doc docnames ty unicode  -- | Pretty-print a type, adding documentation to the whole type and its  -- arguments as needed. @@ -458,7 +467,7 @@ ppTypeOrFunSig typ (doc, argDocs) (pref1, pref2, sep0) unicode          text "\\end{tabulary}\\par" $$          fromMaybe empty (documentationToLaTeX doc) --- This splits up a type signature along `->` and adds docs (when they exist) +-- | This splits up a type signature along @->@ and adds docs (when they exist)  -- to the arguments. The output is a list of (leader/seperator, argument and  -- its doc)  ppSubSigLike :: Bool                  -- ^ unicode @@ -491,8 +500,9 @@ ppSubSigLike unicode typ argDocs subdocs leader = do_sig_args 0 leader typ                <+> ppLType unicode ltype            ) ]      do_args n leader (HsQualTy _ lctxt ltype) -      = (decltt leader, ppLContextNoArrow lctxt unicode <+> nl) -        : do_largs n (darrow unicode) ltype +      = ( decltt leader +        , decltt (ppLContextNoArrow lctxt unicode) <+> nl +        ) : do_largs n (darrow unicode) ltype      do_args n leader (HsFunTy _ _w (L _ (HsRecTy _ fields)) r)        = [ (decltt ldr, latex <+> nl) @@ -511,9 +521,9 @@ ppSubSigLike unicode typ argDocs subdocs leader = do_sig_args 0 leader typ      -- We need 'gadtComma' and 'gadtEnd' to line up with the `{` from      -- 'gadtOpen', so we add 3 spaces to cover for `-> `/`:: ` (3 in unicode      -- mode since `->` and `::` are rendered as single characters. -    gadtComma = hcat (replicate (if unicode then 3 else 4) (text "\\ ")) <> text "," -    gadtEnd = hcat (replicate (if unicode then 3 else 4) (text "\\ ")) <> text "\\}" -    gadtOpen = text "\\{" +    gadtComma = hcat (replicate (if unicode then 3 else 4) (char ' ')) <> char ',' +    gadtEnd = hcat (replicate (if unicode then 3 else 4) (char ' ')) <> char '}' +    gadtOpen = char '{'  ppTypeSig :: [Name] -> HsSigType DocNameI  -> Bool -> LaTeX @@ -547,10 +557,9 @@ declWithDoc :: LaTeX -> Maybe LaTeX -> LaTeX  declWithDoc decl doc =     text "\\begin{haddockdesc}" $$     text "\\item[\\begin{tabular}{@{}l}" $$ -   text (latexMonoFilter (show decl)) $$ -   text "\\end{tabular}]" <> -       (if isNothing doc then empty else text "\\haddockbegindoc") $$ -   maybe empty id doc $$ +   text (latexMonoFilter (latex2String decl)) $$ +   text "\\end{tabular}]" $$ +   maybe empty (\x -> text "{\\haddockbegindoc" $$ x <> text "}") doc $$     text "\\end{haddockdesc}" @@ -561,9 +570,9 @@ multiDecl :: [LaTeX] -> LaTeX  multiDecl decls =     text "\\begin{haddockdesc}" $$     vcat [ -      text "\\item[" $$ -      text (latexMonoFilter (show decl)) $$ -      text "]" +      text "\\item[\\begin{tabular}{@{}l}" $$ +      text (latexMonoFilter (latex2String decl)) $$ +      text "\\end{tabular}]"        | decl <- decls ] $$     text "\\end{haddockdesc}" @@ -607,6 +616,7 @@ ppFds fds unicode =                             hsep (map (ppDocName . unLoc) vars2) +-- TODO: associated type defaults, docs on default methods  ppClassDecl :: [DocInstance DocNameI]              -> Documentation DocName -> [(DocName, DocForDecl DocName)]              -> TyClDecl DocNameI -> Bool -> LaTeX @@ -627,18 +637,28 @@ ppClassDecl instances doc subdocs      body_        | null lsigs, null ats, null at_defs = Nothing        | null ats, null at_defs = Just methodTable ----     | otherwise = atTable $$ methodTable -      | otherwise = error "LaTeX.ppClassDecl" +      | otherwise = Just (atTable $$ methodTable) + +    atTable = +      text "\\haddockpremethods{}" <> emph (text "Associated Types") $$ +      vcat  [ ppFamDecl True (fst doc) [] (FamDecl noExtField decl) True +            | L _ decl <- ats +            , let name = unLoc . fdLName $ decl +                  doc = lookupAnySubdoc name subdocs +            ] +      methodTable =        text "\\haddockpremethods{}" <> emph (text "Methods") $$ -      vcat  [ ppFunSig doc names (dropWildCards 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? +      vcat  [ ppFunSig leader doc names typ unicode +            | L _ (ClassOpSig _ is_def lnames typ) <- lsigs +            , let doc | is_def = noDocForDecl +                      | otherwise = lookupAnySubdoc (head names) subdocs +                  names = map unLoc lnames +                  leader = if is_def then Just (keyword "default") else Nothing +            ] +            -- N.B. taking just the first name is ok. Signatures with multiple +            -- names are expanded so that each name gets its own signature.      instancesBit = ppDocInstances unicode instances @@ -657,6 +677,7 @@ ppDocInstances unicode (i : rest)  isUndocdInstance :: DocInstance a -> Maybe (InstHead a)  isUndocdInstance (i,Nothing,_,_) = Just i +isUndocdInstance (i,Just (MetaDoc _ DocEmpty),_,_) = Just i  isUndocdInstance _ = Nothing  -- | Print a possibly commented instance. The instance header is printed inside @@ -739,15 +760,21 @@ ppDataDecl pats instances subdocs doc dataDecl unicode =  -- ppConstrHdr is for (non-GADT) existentials constructors' syntax -ppConstrHdr :: Bool -> [Name] -> HsContext DocNameI -> Bool -> LaTeX -ppConstrHdr forall tvs ctxt unicode - = (if null tvs then empty else ppForall) -   <+> -   (if null ctxt then empty else ppContextNoArrow ctxt unicode <+> darrow unicode <+> text " ") +ppConstrHdr +  :: Bool                    -- ^ print explicit foralls +  -> [LHsTyVarBndr Specificity DocNameI] -- ^ type variables +  -> HsContext DocNameI      -- ^ context +  -> Bool                    -- ^ unicode +  -> LaTeX +ppConstrHdr forall_ tvs ctxt unicode = ppForall <> ppCtxt    where -    ppForall = case forall of -      True  -> forallSymbol unicode <+> hsep (map ppName tvs) <+> text ". " -      False -> empty +    ppForall +      | null tvs || not forall_ = empty +      | otherwise = ppHsForAllTelescope (mkHsForAllInvisTeleI tvs) unicode + +    ppCtxt +      | null ctxt = empty +      | otherwise = ppContextNoArrow ctxt unicode <+> darrow unicode <> space  -- | Pretty-print a constructor @@ -776,11 +803,10 @@ ppSideBySideConstr subdocs unicode leader (L _ con) =      -- First line of the constructor (no doc, no fields, single-line)      decl = case con of        ConDeclH98{ con_args = det -                , con_ex_tvs = vars +                , con_ex_tvs = tyVars +                , con_forall = L _ forall_                  , con_mb_cxt = cxt -                } -> let tyVars = map (getName . hsLTyVarNameI) vars -                         context = unLoc (fromMaybe (noLoc []) cxt) -                         forall_ = False +                } -> let context = unLoc (fromMaybe (noLoc []) cxt)                           header_ = ppConstrHdr forall_ tyVars context unicode                       in case det of          -- Prefix constructor, e.g. 'Just a' @@ -788,7 +814,7 @@ ppSideBySideConstr subdocs unicode leader (L _ con) =            | hasArgDocs -> header_ <+> ppOcc            | otherwise -> hsep [ header_                                , ppOcc -                              , hsep (map ((ppLParendType unicode) . hsScaledThing) args) +                              , hsep (map (ppLParendType unicode . hsScaledThing) args)                                ]          -- Record constructor, e.g. 'Identity { runIdentity :: a }' @@ -1053,7 +1079,6 @@ ppLKind unicode y = ppKind unicode (unLoc y)  ppKind :: Bool -> HsKind DocNameI -> LaTeX  ppKind unicode ki = ppr_mono_ty (reparenTypePrec PREC_TOP ki) unicode -  -- Drop top-level for-all type variables in user style  -- since they are implicit in Haskell @@ -1089,7 +1114,7 @@ ppr_mono_ty (HsSumTy _ tys) u       = sumParens (map (ppLType u) tys)  ppr_mono_ty (HsKindSig _ ty kind) u = parens (ppr_mono_lty ty u <+> dcolon u <+> ppLKind u kind)  ppr_mono_ty (HsListTy _ ty)       u = brackets (ppr_mono_lty ty u)  ppr_mono_ty (HsIParamTy _ (L _ n) ty) u = ppIPName n <+> dcolon u <+> ppr_mono_lty ty u -ppr_mono_ty (HsSpliceTy {})     _ = error "ppr_mono_ty HsSpliceTy" +ppr_mono_ty (HsSpliceTy v _)    _ = absurd v  ppr_mono_ty (HsRecTy {})        _ = text "{..}"  ppr_mono_ty (XHsType {})        _ = error "ppr_mono_ty HsCoreTy"  ppr_mono_ty (HsExplicitListTy _ IsPromoted tys) u = Pretty.quote $ brackets $ hsep $ punctuate comma $ map (ppLType u) tys @@ -1115,7 +1140,7 @@ ppr_mono_ty (HsParTy _ ty) unicode  ppr_mono_ty (HsDocTy _ ty _) unicode    = ppr_mono_lty ty unicode -ppr_mono_ty (HsWildCardTy _) _ = text "\\_" +ppr_mono_ty (HsWildCardTy _) _ = char '_'  ppr_mono_ty (HsTyLit _ t) u = ppr_tylit t u  ppr_mono_ty (HsStarTy _ isUni) unicode = starSymbol (isUni || unicode) @@ -1150,9 +1175,6 @@ ppSymName name    | otherwise = ppName name -ppVerbOccName :: OccName -> LaTeX -ppVerbOccName = text . latexFilter . occNameString -  ppIPName :: HsIPName -> LaTeX  ppIPName = text . ('?':) . unpackFS . hsIPNameFS @@ -1160,18 +1182,9 @@ ppOccName :: OccName -> LaTeX  ppOccName = text . occNameString -ppVerbDocName :: DocName -> LaTeX -ppVerbDocName = ppVerbOccName . nameOccName . getName - - -ppVerbRdrName :: RdrName -> LaTeX -ppVerbRdrName = ppVerbOccName . rdrNameOcc - -  ppDocName :: DocName -> LaTeX  ppDocName = ppOccName . nameOccName . getName -  ppLDocName :: Located DocName -> LaTeX  ppLDocName (L _ d) = ppDocName d @@ -1209,9 +1222,10 @@ latexMunge c    s = c : s  latexMonoMunge :: Char -> String -> String -latexMonoMunge ' ' s = '\\' : ' ' : s +latexMonoMunge ' '      (' ':s) = "\\ \\ " ++ s +latexMonoMunge ' ' ('\\':' ':s) = "\\ \\ " ++ s  latexMonoMunge '\n' s = '\\' : '\\' : s -latexMonoMunge c   s = latexMunge c s +latexMonoMunge c s = latexMunge c s  ------------------------------------------------------------------------------- @@ -1219,34 +1233,40 @@ latexMonoMunge c   s = latexMunge c s  ------------------------------------------------------------------------------- -parLatexMarkup :: (a -> LaTeX) -> DocMarkup a (StringContext -> LaTeX) -parLatexMarkup ppId = Markup { -  markupParagraph            = \p v -> p v <> text "\\par" $$ text "", -  markupEmpty                = \_ -> empty, -  markupString               = \s v -> text (fixString v s), -  markupAppend               = \l r v -> l v <> r v, -  markupIdentifier           = markupId ppId, -  markupIdentifierUnchecked  = markupId (ppVerbOccName . snd), -  markupModule               = \m _ -> let (mdl,_ref) = break (=='#') m in tt (text mdl), -  markupWarning              = \p v -> emph (p v), -  markupEmphasis             = \p v -> emph (p v), -  markupBold                 = \p v -> bold (p v), -  markupMonospaced           = \p _ -> tt (p Mono), -  markupUnorderedList        = \p v -> itemizedList (map ($ v) p) $$ text "", -  markupPic                  = \p _ -> markupPic p, -  markupMathInline           = \p _ -> markupMathInline p, -  markupMathDisplay          = \p _ -> markupMathDisplay p, -  markupOrderedList          = \p v -> enumeratedList (map ($ v) p) $$ text "", -  markupDefList              = \l v -> descriptionList (map (\(a,b) -> (a v, b v)) l), -  markupCodeBlock            = \p _ -> quote (verb (p Verb)) $$ text "", -  markupHyperlink            = \(Hyperlink u l) p -> markupLink u (fmap ($ p) l), -  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), -  markupTable                = \(Table h b) p -> table h b p +latexMarkup :: HasOccName a => DocMarkup (Wrap a) (StringContext -> LaTeX -> LaTeX) +latexMarkup = Markup +  { markupParagraph            = \p v -> blockElem (p v (text "\\par")) +  , markupEmpty                = \_ -> id +  , markupString               = \s v -> inlineElem (text (fixString v s)) +  , markupAppend               = \l r v -> l v . r v +  , markupIdentifier           = \i v -> inlineElem (markupId v (fmap occName i)) +  , markupIdentifierUnchecked  = \i v -> inlineElem (markupId v (fmap snd i)) +  , markupModule               = \m _ -> inlineElem (let (mdl,_ref) = break (=='#') m in (tt (text mdl))) +  , markupWarning              = \p v -> p v +  , markupEmphasis             = \p v -> inlineElem (emph (p v empty)) +  , markupBold                 = \p v -> inlineElem (bold (p v empty)) +  , markupMonospaced           = \p v -> inlineElem (markupMonospace p v) +  , markupUnorderedList        = \p v -> blockElem (itemizedList (map (\p' -> p' v empty) p)) +  , markupPic                  = \p _ -> inlineElem (markupPic p) +  , markupMathInline           = \p _ -> inlineElem (markupMathInline p) +  , markupMathDisplay          = \p _ -> blockElem (markupMathDisplay p) +  , markupOrderedList          = \p v -> blockElem (enumeratedList (map (\p' -> p' v empty) p)) +  , markupDefList              = \l v -> blockElem (descriptionList (map (\(a,b) -> (a v empty, b v empty)) l)) +  , markupCodeBlock            = \p _ -> blockElem (quote (verb (p Verb empty))) +  , markupHyperlink            = \(Hyperlink u l) v -> inlineElem (markupLink u (fmap (\x -> x v empty) l)) +  , markupAName                = \_ _ -> id -- TODO +  , markupProperty             = \p _ -> blockElem (quote (verb (text p))) +  , markupExample              = \e _ -> blockElem (quote (verb (text $ unlines $ map exampleToString e))) +  , markupHeader               = \(Header l h) p -> blockElem (header l (h p empty)) +  , markupTable                = \(Table h b) p -> blockElem (table h b p)    }    where +    blockElem :: LaTeX -> LaTeX -> LaTeX +    blockElem = ($$) + +    inlineElem :: LaTeX -> LaTeX -> LaTeX +    inlineElem = (<>) +      header 1 d = text "\\section*" <> braces d      header 2 d = text "\\subsection*" <> braces d      header l d @@ -1259,6 +1279,9 @@ parLatexMarkup ppId = Markup {      fixString Verb  s = s      fixString Mono  s = latexMonoFilter s +    markupMonospace p Verb = p Verb empty +    markupMonospace p _ = tt (p Mono empty) +      markupLink url mLabel = case mLabel of        Just label -> text "\\href" <> braces (text url) <> braces label        Nothing    -> text "\\url"  <> braces (text url) @@ -1275,35 +1298,28 @@ parLatexMarkup ppId = Markup {      markupMathDisplay mathjax = text "\\[" <> text mathjax <> text "\\]" -    markupId ppId_ id v = +    markupId v wrappedOcc =        case v of -        Verb  -> theid -        Mono  -> theid -        Plain -> text "\\haddockid" <> braces theid -      where theid = ppId_ id - - -latexMarkup :: DocMarkup DocName (StringContext -> LaTeX) -latexMarkup = parLatexMarkup ppVerbDocName - - -rdrLatexMarkup :: DocMarkup RdrName (StringContext -> LaTeX) -rdrLatexMarkup = parLatexMarkup ppVerbRdrName - +        Verb  -> text i +        Mono  -> text "\\haddockid" <> braces (text . latexMonoFilter $ i) +        Plain -> text "\\haddockid" <> braces (text . latexFilter $ i) +      where i = showWrapped occNameString wrappedOcc  docToLaTeX :: Doc DocName -> LaTeX -docToLaTeX doc = markup latexMarkup doc Plain - +docToLaTeX doc = markup latexMarkup doc Plain empty  documentationToLaTeX :: Documentation DocName -> Maybe LaTeX  documentationToLaTeX = fmap docToLaTeX . fmap _doc . combineDocumentation  rdrDocToLaTeX :: Doc RdrName -> LaTeX -rdrDocToLaTeX doc = markup rdrLatexMarkup doc Plain +rdrDocToLaTeX doc = markup latexMarkup doc Plain empty -data StringContext = Plain | Verb | Mono +data StringContext +  = Plain  -- ^ all special characters have to be escape +  | Mono   -- ^ on top of special characters, escape space chraacters +  | Verb   -- ^ don't escape anything  latexStripTrailingWhitespace :: Doc a -> Doc a @@ -1328,23 +1344,23 @@ latexStripTrailingWhitespace other = other  itemizedList :: [LaTeX] -> LaTeX  itemizedList items = -  text "\\begin{itemize}" $$ +  text "\\vbox{\\begin{itemize}" $$    vcat (map (text "\\item" $$) items) $$ -  text "\\end{itemize}" +  text "\\end{itemize}}"  enumeratedList :: [LaTeX] -> LaTeX  enumeratedList items = -  text "\\begin{enumerate}" $$ +  text "\\vbox{\\begin{enumerate}" $$    vcat (map (text "\\item " $$) items) $$ -  text "\\end{enumerate}" +  text "\\end{enumerate}}"  descriptionList :: [(LaTeX,LaTeX)] -> LaTeX  descriptionList items = -  text "\\begin{description}" $$ -  vcat (map (\(a,b) -> text "\\item" <> brackets a <+> b) items) $$ -  text "\\end{description}" +  text "\\vbox{\\begin{description}" $$ +  vcat (map (\(a,b) -> text "\\item" <> brackets a <> text "\\hfill \\par" $$ b) items) $$ +  text "\\end{description}}"  tt :: LaTeX -> LaTeX @@ -1352,8 +1368,8 @@ tt ltx = text "\\haddocktt" <> braces ltx  decltt :: LaTeX -> LaTeX -decltt ltx = text "\\haddockdecltt" <> braces ltx - +decltt ltx = text "\\haddockdecltt" <> braces (text filtered) +  where filtered = latexMonoFilter (latex2String ltx)  emph :: LaTeX -> LaTeX  emph ltx = text "\\emph" <> braces ltx @@ -1361,6 +1377,12 @@ emph ltx = text "\\emph" <> braces ltx  bold :: LaTeX -> LaTeX  bold ltx = text "\\textbf" <> braces ltx +-- TODO: @verbatim@ is too much since +-- +--   * Haddock supports markup _inside_ of codeblocks. Right now, the LaTeX +--     representing that markup gets printed verbatim +--   * Verbatim environments are not supported everywhere (example: not nested +--     inside a @tabulary@ environment)  verb :: LaTeX -> LaTeX  verb doc = text "{\\haddockverb\\begin{verbatim}" $$ doc <> text "\\end{verbatim}}"     -- NB. swallow a trailing \n in the verbatim text by appending the diff --git a/haddock-api/src/Haddock/Backends/Xhtml.hs b/haddock-api/src/Haddock/Backends/Xhtml.hs index 3453bb0c..1bdbf81b 100644 --- a/haddock-api/src/Haddock/Backends/Xhtml.hs +++ b/haddock-api/src/Haddock/Backends/Xhtml.hs @@ -292,6 +292,10 @@ ppHtmlContents state odir doctitle _maybe_package            ]    createDirectoryIfMissing True odir    writeUtf8File (joinPath [odir, contentsHtmlFile]) (renderToString debug html) +  where +    -- Extract a module's short description. +    toInstalledDescription :: InstalledInterface -> Maybe (MDoc Name) +    toInstalledDescription = fmap mkMeta . hmi_description . instInfo  ppPrologue :: Maybe Package -> Qualification -> String -> Maybe (MDoc GHC.RdrName) -> Html @@ -301,6 +305,7 @@ ppPrologue pkg qual title (Just doc) =  ppSignatureTree :: Maybe Package -> Qualification -> [ModuleTree] -> Html +ppSignatureTree _ _ [] = mempty  ppSignatureTree pkg qual ts =    divModuleList << (sectionName << "Signatures" +++ mkNodeList pkg qual [] "n" ts) @@ -666,16 +671,22 @@ numberSectionHeadings = go 1    where go :: Int -> [ExportItem DocNameI] -> [ExportItem DocNameI]          go _ [] = []          go n (ExportGroup lev _ doc : es) -          = ExportGroup lev (show n) doc : go (n+1) es +          = case collectAnchors doc of +              [] -> ExportGroup lev (show n) doc : go (n+1) es +              (a:_) -> ExportGroup lev a doc : go (n+1) es          go n (other:es)            = other : go n es +        collectAnchors :: DocH (Wrap (ModuleName, OccName)) (Wrap DocName) -> [String] +        collectAnchors (DocAppend a b) = collectAnchors a ++ collectAnchors b +        collectAnchors (DocAName a) = [a] +        collectAnchors _ = []  processExport :: Bool -> LinksInfo -> Bool -> Maybe Package -> Qualification                -> ExportItem DocNameI -> Maybe Html  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) +  = nothingIf summary $ groupHeading lev id0 << docToHtmlNoAnchors (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 []) diff --git a/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs b/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs index 6a879a0d..de37e42a 100644 --- a/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs +++ b/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs @@ -32,6 +32,7 @@ import Haddock.Doc (combineDocumentation)  import           Data.List             ( intersperse, sort )  import qualified Data.Map as Map  import           Data.Maybe +import           Data.Void             ( absurd )  import           Text.XHtml hiding     ( name, title, p, quote )  import GHC.Core.Type ( Specificity(..) ) @@ -75,14 +76,14 @@ ppLFunSig :: Bool -> LinksInfo -> SrcSpan -> DocForDecl DocName ->               [Located DocName] -> LHsSigType DocNameI -> [(DocName, Fixity)] ->               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 +  ppFunSig summary links loc noHtml doc (map unLoc lnames) lty fixities             splice unicode pkg qual -ppFunSig :: Bool -> LinksInfo -> SrcSpan -> DocForDecl DocName -> +ppFunSig :: Bool -> LinksInfo -> SrcSpan -> Html -> DocForDecl DocName ->              [DocName] -> LHsSigType DocNameI -> [(DocName, Fixity)] ->              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) +ppFunSig summary links loc leader doc docnames typ fixities splice unicode pkg qual = +  ppSigLike summary links loc leader doc docnames fixities (unLoc typ, pp_typ)              splice unicode pkg qual HideEmptyContexts    where      pp_typ = ppLSigType unicode qual HideEmptyContexts typ @@ -133,8 +134,8 @@ ppTypeOrFunSig summary links loc docnames typ (doc, argDocs) (pref1, pref2, sep)      curname = getName <$> listToMaybe docnames --- This splits up a type signature along `->` and adds docs (when they exist) to --- the arguments. +-- | This splits up a type signature along @->@ and adds docs (when they exist) +-- to the arguments.  --  -- If one passes in a list of the available subdocs, any top-level `HsRecTy`  -- found will be expanded out into their fields. @@ -152,7 +153,7 @@ ppSubSigLike unicode qual typ argDocs subdocs sep emptyCtxts = do_sig_args 0 sep          HsOuterExplicit{hso_bndrs = bndrs} -> do_largs n (leader' bndrs) ltype          HsOuterImplicit{}                  -> do_largs n leader          ltype        where -        leader' bndrs = leader <+> ppForAll (mkHsForAllInvisTeleI bndrs) unicode qual +        leader' bndrs = leader <+> ppForAllPart unicode qual (mkHsForAllInvisTeleI bndrs)      argDoc n = Map.lookup n argDocs @@ -163,7 +164,7 @@ ppSubSigLike unicode qual typ argDocs subdocs sep emptyCtxts = do_sig_args 0 sep      do_args n leader (HsForAllTy _ tele ltype)        = do_largs n leader' ltype        where -        leader' = leader <+> ppForAll tele unicode qual +        leader' = leader <+> ppForAllPart unicode qual tele      do_args n leader (HsQualTy _ lctxt ltype)        | null (unLoc lctxt) @@ -197,24 +198,6 @@ ppSubSigLike unicode qual typ argDocs subdocs sep emptyCtxts = do_sig_args 0 sep      gadtOpen = toHtml "{" - -ppForAll :: HsForAllTelescope DocNameI -> Unicode -> Qualification -         -> Html -ppForAll tele unicode qual = case tele of -  HsForAllVis { hsf_vis_bndrs = bndrs } -> -    pp_bndrs bndrs (spaceHtml +++ arrow unicode) -  HsForAllInvis { hsf_invis_bndrs = bndrs } -> -    pp_bndrs bndrs dot -  where -    pp_bndrs :: [LHsTyVarBndr flag DocNameI] -> Html -> Html -    pp_bndrs tvs forall_separator = -      case [pp_ktv n k | L _ (KindedTyVar _ _ (L _ n) k) <- tvs] of -        [] -> noHtml -        ts -> forallSymbol unicode <+> hsep ts +++ forall_separator - -    pp_ktv n k = parens $ -      ppTyName (getName n) <+> dcolon unicode <+> ppLKind unicode qual k -  ppFixities :: [(DocName, Fixity)] -> Qualification -> Html  ppFixities [] _ = noHtml  ppFixities fs qual = foldr1 (+++) (map ppFix uniq_fs) +++ rightEdge @@ -248,7 +231,7 @@ ppFor :: Bool -> LinksInfo -> SrcSpan -> DocForDecl DocName        -> Splice -> Unicode -> Maybe Package -> Qualification -> Html  ppFor summary links loc doc (ForeignImport _ (L _ name) typ _) fixities        splice unicode pkg qual -  = ppFunSig summary links loc doc [name] typ fixities splice unicode pkg qual +  = ppFunSig summary links loc noHtml doc [name] typ fixities splice unicode pkg qual  ppFor _ _ _ _ _ _ _ _ _ _ = error "ppFor" @@ -280,11 +263,6 @@ ppTypeSig summary nms pp_ty unicode =    where      htmlNames = intersperse (stringToHtml ", ") $ map (ppBinder summary) nms - -ppTyName :: Name -> Html -ppTyName = ppName Prefix - -  ppSimpleSig :: LinksInfo -> Splice -> Unicode -> Qualification -> HideEmptyContexts -> SrcSpan              -> [DocName] -> HsSigType DocNameI              -> Html @@ -528,7 +506,7 @@ ppShortClassDecl summary links (ClassDecl { tcdCtxt = lctxt, tcdLName = lname, t                  -- ToDo: add associated type defaults -            [ ppFunSig summary links loc doc names typ +            [ ppFunSig summary links loc noHtml doc names typ                         [] splice unicode pkg qual                | L _ (ClassOpSig _ False lnames typ) <- sigs                , let doc = lookupAnySubdoc (head names) subdocs @@ -550,7 +528,7 @@ ppClassDecl :: Bool -> LinksInfo -> [DocInstance DocNameI] -> [(DocName, Fixity)              -> 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 }) +                        , tcdFDs = lfds, tcdSigs = lsigs, tcdATs = ats, tcdATDefs = atsDefs })              splice unicode pkg qual    | summary = ppShortClassDecl summary links decl loc subdocs splice unicode pkg qual    | otherwise = classheader +++ docSection curname pkg qual d @@ -571,24 +549,61 @@ 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 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 [name] typ -                                      subfixs splice unicode pkg qual -                           | L _ (ClassOpSig _ _ lnames typ) <- lsigs -                           , 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. +    -- Associated types +    atBit = subAssociatedTypes +      [ ppAssocType summary links doc at subfixs splice unicode pkg qual +          <+> +        subDefaults (maybeToList defTys) +      | at <- ats +      , let name = unLoc . fdLName $ unLoc at +            doc = lookupAnySubdoc name subdocs +            subfixs = filter ((== name) . fst) fixities +            defTys = (declElem . ppDefaultAssocTy name) <$> lookupDAT name +      ] + +    -- Default associated types +    ppDefaultAssocTy n (vs,rhs) = hsep +      [ keyword "type", ppAppNameTypeArgs n vs unicode qual, equals +      , ppType unicode qual HideEmptyContexts (unLoc rhs) +      ] + +    lookupDAT name = Map.lookup (getName name) defaultAssocTys +    defaultAssocTys = Map.fromList +      [ (getName name, (vs, typ)) +      | L _ (TyFamInstDecl (FamEqn { feqn_rhs = typ +                                   , feqn_tycon = L _ name +                                   , feqn_pats = vs })) <- atsDefs +      ] +    -- Methods +    methodBit = subMethods +      [ ppFunSig summary links loc noHtml doc [name] typ +                 subfixs splice unicode pkg qual +          <+> +        subDefaults (maybeToList defSigs) +      | ClassOpSig _ False lnames typ <- sigs +      , name <- map unLoc lnames +      , let doc = lookupAnySubdoc name subdocs +            subfixs = filter ((== name)  . fst) fixities +            defSigs = ppDefaultFunSig name <$> lookupDM name +      ] +      -- N.B. taking just the first name is ok. Signatures with multiple names +      -- are expanded so that each name gets its own signature. + +    -- Default methods +    ppDefaultFunSig n (t, d') = ppFunSig summary links loc (keyword "default") +      d' [n] t [] splice unicode pkg qual + +    lookupDM name = Map.lookup (getOccString name) defaultMethods +    defaultMethods = Map.fromList +      [ (nameStr, (typ, doc)) +      | ClassOpSig _ True lnames typ <- sigs +      , name <- map unLoc lnames +      , let doc = noDocForDecl -- TODO: get docs for method defaults +            nameStr = getOccString name +      ] + +    -- Minimal complete definition      minimalBit = case [ s | MinimalSig _ _ (L _ s) <- sigs ] of        -- Miminal complete definition = every shown method        And xs : _ | sort [getName n | L _ (Var (L _ n)) <- xs] == @@ -612,6 +627,7 @@ ppClassDecl summary links instances fixities loc d subdocs        where wrap | p = parens | otherwise = id      ppMinimal p (Parens x) = ppMinimal p (unLoc x) +    -- Instances      instancesBit = ppInstances links (OriginClass nm) instances          splice unicode pkg qual @@ -836,18 +852,16 @@ ppShortConstrParts :: Bool -> Bool -> ConDecl DocNameI -> Unicode -> Qualificati  ppShortConstrParts summary dataInst con unicode qual    = case con of        ConDeclH98{ con_args = det -                , con_ex_tvs = vars +                , con_ex_tvs = tyVars +                , con_forall = L _ forall_                  , con_mb_cxt = cxt -                } -> let tyVars = map (getName . hsLTyVarNameI) vars -                         context = unLoc (fromMaybe (noLoc []) cxt) -                         forall_ = False +                } -> let context = unLoc (fromMaybe (noLoc []) cxt)                           header_ = ppConstrHdr forall_ tyVars context unicode qual                       in case det of          -- Prefix constructor, e.g. 'Just a'          PrefixCon _ args -> -          ( header_ +++ -              hsep (ppOcc : map ((ppLParendType unicode qual HideEmptyContexts) . hsScaledThing) args) +          ( header_ <+> hsep (ppOcc : map (ppLParendType unicode qual HideEmptyContexts . hsScaledThing) args)            , noHtml            , noHtml            ) @@ -863,7 +877,7 @@ ppShortConstrParts summary dataInst con unicode qual          -- Infix constructor, e.g. 'a :| [a]'          InfixCon arg1 arg2 -> -          ( header_ +++ hsep [ ppLParendType unicode qual HideEmptyContexts (hsScaledThing arg1) +          ( header_ <+> hsep [ ppLParendType unicode qual HideEmptyContexts (hsScaledThing arg1)                               , ppOccInfix                               , ppLParendType unicode qual HideEmptyContexts (hsScaledThing arg2)                               ] @@ -910,28 +924,27 @@ ppSideBySideConstr subdocs fixities unicode pkg qual (L _ con)      decl = case con of        ConDeclH98{ con_args = det -                , con_ex_tvs = vars +                , con_ex_tvs = tyVars +                , con_forall = L _ forall_                  , con_mb_cxt = cxt -                } -> let tyVars = map (getName . hsLTyVarNameI) vars -                         context = unLoc (fromMaybe (noLoc []) cxt) -                         forall_ = False +                } -> let context = unLoc (fromMaybe (noLoc []) cxt)                           header_ = ppConstrHdr forall_ tyVars context unicode qual                       in case det of          -- Prefix constructor, e.g. 'Just a'          PrefixCon _ args -          | hasArgDocs -> header_ +++ ppOcc <+> fixity -          | otherwise -> hsep [ header_ +++ ppOcc -                              , hsep (map ((ppLParendType unicode qual HideEmptyContexts) . hsScaledThing) args) +          | hasArgDocs -> header_ <+> ppOcc <+> fixity +          | otherwise -> hsep [ header_ <+> ppOcc +                              , hsep (map (ppLParendType unicode qual HideEmptyContexts . hsScaledThing) args)                                , fixity                                ]          -- Record constructor, e.g. 'Identity { runIdentity :: a }' -        RecCon _ -> header_ +++ ppOcc <+> fixity +        RecCon _ -> header_ <+> ppOcc <+> fixity          -- Infix constructor, e.g. 'a :| [a]'          InfixCon arg1 arg2 -          | hasArgDocs -> header_ +++ ppOcc <+> fixity -          | otherwise -> hsep [ header_ +++ ppLParendType unicode qual HideEmptyContexts (hsScaledThing arg1) +          | hasArgDocs -> header_ <+> ppOcc <+> fixity +          | otherwise -> hsep [ header_ <+> ppLParendType unicode qual HideEmptyContexts (hsScaledThing arg1)                                , ppOccInfix                                , ppLParendType unicode qual HideEmptyContexts (hsScaledThing arg2)                                , fixity @@ -984,17 +997,17 @@ ppSideBySideConstr subdocs fixities unicode pkg qual (L _ con)  -- ppConstrHdr is for (non-GADT) existentials constructors' syntax -ppConstrHdr :: Bool               -- ^ print explicit foralls -            -> [Name]             -- ^ type variables -            -> HsContext DocNameI -- ^ context -            -> Unicode -> Qualification -> Html +ppConstrHdr +  :: Bool                    -- ^ print explicit foralls +  -> [LHsTyVarBndr Specificity DocNameI] -- ^ type variables +  -> HsContext DocNameI      -- ^ context +  -> Unicode -> Qualification +  -> Html  ppConstrHdr forall_ tvs ctxt unicode qual = ppForall +++ ppCtxt    where      ppForall        | null tvs || not forall_ = noHtml -      | otherwise = forallSymbol unicode -                      <+> hsep (map (ppName Prefix) tvs) -                      <+> toHtml ". " +      | otherwise = ppForAllPart unicode qual (HsForAllInvis noExtField tvs)      ppCtxt        | null ctxt = noHtml @@ -1240,11 +1253,11 @@ ppr_mono_ty (HsTupleTy _ con tys) u q _ =  ppr_mono_ty (HsSumTy _ tys) u q _ =    sumParens (map (ppLType u q HideEmptyContexts) tys)  ppr_mono_ty (HsKindSig _ ty kind) u q e = -  parens (ppr_mono_lty ty u q e <+> dcolon u <+> ppLKind u q kind) +  ppr_mono_lty ty u q e <+> dcolon u <+> ppLKind u q kind  ppr_mono_ty (HsListTy _ ty)       u q _ = brackets (ppr_mono_lty ty u q HideEmptyContexts)  ppr_mono_ty (HsIParamTy _ (L _ n) ty) u q _ =    ppIPName n <+> dcolon u <+> ppr_mono_lty ty u q HideEmptyContexts -ppr_mono_ty (HsSpliceTy {})     _ _ _ = error "ppr_mono_ty HsSpliceTy" +ppr_mono_ty (HsSpliceTy v _) _ _ _ = absurd v  ppr_mono_ty (HsRecTy {})        _ _ _ = toHtml "{..}"         -- Can now legally occur in ConDeclGADT, the output here is to provide a         -- placeholder in the signature, which is followed by the field diff --git a/haddock-api/src/Haddock/Backends/Xhtml/DocMarkup.hs b/haddock-api/src/Haddock/Backends/Xhtml/DocMarkup.hs index ee90ad68..378d0559 100644 --- a/haddock-api/src/Haddock/Backends/Xhtml/DocMarkup.hs +++ b/haddock-api/src/Haddock/Backends/Xhtml/DocMarkup.hs @@ -19,7 +19,7 @@ module Haddock.Backends.Xhtml.DocMarkup (    docElement, docSection, docSection_,  ) where -import Data.List +import Data.List (intersperse)  import Documentation.Haddock.Markup  import Haddock.Backends.Xhtml.Names  import Haddock.Backends.Xhtml.Utils @@ -171,18 +171,18 @@ 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 -> Maybe Package -> Hack (ModuleName, OccName) id -> Html +hackMarkup :: DocMarkup id Html -> Maybe Package -> Hack (Wrap (ModuleName, OccName)) id -> Html  hackMarkup fmt' currPkg h' =    let (html, ms) = hackMarkup' fmt' h'    in html +++ renderMeta fmt' currPkg (metaConcat ms)    where -    hackMarkup' :: DocMarkup id Html -> Hack (ModuleName, OccName) id +    hackMarkup' :: DocMarkup id Html -> Hack (Wrap (ModuleName, OccName)) id                  -> (Html, [Meta])      hackMarkup' fmt h = case h of        UntouchedDoc d -> (markup fmt $ _doc d, [_meta d])        CollapsingHeader (Header lvl titl) par n nm ->          let id_ = makeAnchorId $ "ch:" ++ fromMaybe "noid:" nm ++ show n -            col' = collapseControl id_ "caption" +            col' = collapseControl id_ "subheading"              summary = thesummary ! [ theclass "hide-when-js-enabled" ] << "Expand"              instTable contents = collapseDetails id_ DetailsClosed (summary +++ contents)              lvs = zip [1 .. ] [h1, h2, h3, h4, h5, h6] @@ -206,7 +206,7 @@ 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 +markupHacked :: DocMarkup (Wrap id) Html               -> Maybe Package      -- this package               -> Maybe String               -> MDoc id @@ -220,7 +220,7 @@ docToHtml :: Maybe String  -- ^ Name of the thing this doc is for. See            -> Maybe Package -- ^ Current package            -> Qualification -> MDoc DocName -> Html  docToHtml n pkg qual = markupHacked fmt pkg n . cleanup -  where fmt = parHtmlMarkup qual True (ppDocName qual Raw) +  where fmt = parHtmlMarkup qual True (ppWrappedDocName qual Raw)  -- | Same as 'docToHtml' but it doesn't insert the 'anchor' element  -- in links. This is used to generate the Contents box elements. @@ -228,16 +228,16 @@ docToHtmlNoAnchors :: Maybe String  -- ^ See 'toHack'                     -> Maybe Package -- ^ Current package                     -> Qualification -> MDoc DocName -> Html  docToHtmlNoAnchors n pkg qual = markupHacked fmt pkg n . cleanup -  where fmt = parHtmlMarkup qual False (ppDocName qual Raw) +  where fmt = parHtmlMarkup qual False (ppWrappedDocName qual Raw)  origDocToHtml :: Maybe Package -> Qualification -> MDoc Name -> Html  origDocToHtml pkg qual = markupHacked fmt pkg Nothing . cleanup -  where fmt = parHtmlMarkup qual True (const $ ppName Raw) +  where fmt = parHtmlMarkup qual True (const (ppWrappedName Raw))  rdrDocToHtml :: Maybe Package -> Qualification -> MDoc RdrName -> Html  rdrDocToHtml pkg qual = markupHacked fmt pkg Nothing . cleanup -  where fmt = parHtmlMarkup qual True (const ppRdrName) +  where fmt = parHtmlMarkup qual True (const (ppRdrName . unwrap))  docElement :: (Html -> Html) -> Html -> Html @@ -273,7 +273,7 @@ cleanup = overDoc (markup fmtUnParagraphLists)      unParagraph (DocParagraph d) = d      unParagraph doc              = doc -    fmtUnParagraphLists :: DocMarkup a (Doc a) +    fmtUnParagraphLists :: DocMarkup (Wrap a) (Doc a)      fmtUnParagraphLists = idMarkup {        markupUnorderedList = DocUnorderedList . map unParagraph,        markupOrderedList   = DocOrderedList   . map unParagraph diff --git a/haddock-api/src/Haddock/Backends/Xhtml/Layout.hs b/haddock-api/src/Haddock/Backends/Xhtml/Layout.hs index dd8b0b18..d61d6d9b 100644 --- a/haddock-api/src/Haddock/Backends/Xhtml/Layout.hs +++ b/haddock-api/src/Haddock/Backends/Xhtml/Layout.hs @@ -35,6 +35,7 @@ module Haddock.Backends.Xhtml.Layout (    subInstances, subOrphanInstances,    subInstHead, subInstDetails, subFamInstDetails,    subMethods, +  subDefaults,    subMinimal,    topDeclElem, declElem, @@ -259,6 +260,9 @@ instAnchorId iid = makeAnchorId $ "i:" ++ iid  subMethods :: [Html] -> Html  subMethods = divSubDecls "methods" "Methods" . subBlock +subDefaults :: [Html] -> Html +subDefaults = divSubDecls "default" "" . subBlock +  subMinimal :: Html -> Html  subMinimal = divSubDecls "minimal" "Minimal complete definition" . Just . declElem diff --git a/haddock-api/src/Haddock/Backends/Xhtml/Names.hs b/haddock-api/src/Haddock/Backends/Xhtml/Names.hs index 83279f70..8553cdfb 100644 --- a/haddock-api/src/Haddock/Backends/Xhtml/Names.hs +++ b/haddock-api/src/Haddock/Backends/Xhtml/Names.hs @@ -13,7 +13,8 @@  module Haddock.Backends.Xhtml.Names (    ppName, ppDocName, ppLDocName, ppRdrName, ppUncheckedLink,    ppBinder, ppBinderInfix, ppBinder', -  ppModule, ppModuleRef, ppIPName, linkId, Notation(..) +  ppModule, ppModuleRef, ppIPName, linkId, Notation(..), +  ppWrappedDocName, ppWrappedName,  ) where @@ -24,7 +25,7 @@ import Haddock.Utils  import Text.XHtml hiding ( name, p, quote )  import qualified Data.Map as M -import qualified Data.List as List +import Data.List ( stripPrefix )  import GHC hiding (LexicalFixity(..))  import GHC.Types.Name @@ -49,9 +50,11 @@ ppIPName :: HsIPName -> Html  ppIPName = toHtml . ('?':) . unpackFS . hsIPNameFS -ppUncheckedLink :: Qualification -> (ModuleName, OccName) -> Html -ppUncheckedLink _ (mdl, occ) = linkIdOcc' mdl (Just occ) << ppOccName occ -- TODO: apply ppQualifyName - +ppUncheckedLink :: Qualification -> Wrap (ModuleName, OccName) -> Html +ppUncheckedLink _ x = linkIdOcc' mdl (Just occ) << occHtml +  where +    (mdl, occ) = unwrap x +    occHtml = toHtml (showWrapped (occNameString . snd) x) -- TODO: apply ppQualifyName  -- The Bool indicates if it is to be rendered in infix notation  ppLDocName :: Qualification -> Notation -> Located DocName -> Html @@ -68,6 +71,19 @@ ppDocName qual notation insertAnchors docName =            ppQualifyName qual notation name (nameModule name)        | otherwise -> ppName notation name + +ppWrappedDocName :: Qualification -> Notation -> Bool -> Wrap DocName -> Html +ppWrappedDocName qual notation insertAnchors docName = case docName of +  Unadorned n -> ppDocName qual notation insertAnchors n +  Parenthesized n -> ppDocName qual Prefix insertAnchors n +  Backticked n -> ppDocName qual Infix insertAnchors n + +ppWrappedName :: Notation -> Wrap Name -> Html +ppWrappedName notation docName = case docName of +  Unadorned n -> ppName notation n +  Parenthesized n -> ppName Prefix n +  Backticked n -> ppName Infix n +  -- | Render a name depending on the selected qualification mode  ppQualifyName :: Qualification -> Notation -> Name -> Module -> Html  ppQualifyName qual notation name mdl = @@ -79,7 +95,7 @@ ppQualifyName qual notation name mdl =          then ppName notation name          else ppFullQualName notation mdl name      RelativeQual localmdl -> -      case List.stripPrefix (moduleString localmdl) (moduleString mdl) of +      case stripPrefix (moduleString localmdl) (moduleString mdl) of          -- local, A.x -> x          Just []      -> ppName notation name          -- sub-module, A.B.x -> B.x diff --git a/haddock-api/src/Haddock/Backends/Xhtml/Themes.hs b/haddock-api/src/Haddock/Backends/Xhtml/Themes.hs index 10d6ab10..b1d64acd 100644 --- a/haddock-api/src/Haddock/Backends/Xhtml/Themes.hs +++ b/haddock-api/src/Haddock/Backends/Xhtml/Themes.hs @@ -58,7 +58,7 @@ standardTheme :: FilePath -> IO PossibleThemes  standardTheme libDir = liftM (liftEither (take 1)) (defaultThemes libDir) --- | Default themes that are part of Haddock; added with --default-themes +-- | Default themes that are part of Haddock; added with @--built-in-themes@  -- The first theme in this list is considered the standard theme.  -- Themes are "discovered" by scanning the html sub-dir of the libDir,  -- and looking for directories with the extension .theme or .std-theme. diff --git a/haddock-api/src/Haddock/Convert.hs b/haddock-api/src/Haddock/Convert.hs index b866218f..10e13152 100644 --- a/haddock-api/src/Haddock/Convert.hs +++ b/haddock-api/src/Haddock/Convert.hs @@ -57,8 +57,7 @@ import GHC.Parser.Annotation (IsUnicodeSyntax(..))  import Haddock.Types  import Haddock.Interface.Specialize -import Haddock.GhcUtils                      ( orderedFVs, defaultRuntimeRepVars ) -import Haddock.Utils                         ( mkEmptySigType ) +import Haddock.GhcUtils                      ( orderedFVs, defaultRuntimeRepVars, mkEmptySigType )  import Data.Maybe                            ( catMaybes, mapMaybe, maybeToList ) @@ -167,8 +166,7 @@ synifyAxBranch tc (CoAxBranch { cab_tvs = tkvs, cab_lhs = args, cab_rhs = rhs })    = let name            = synifyName tc          args_types_only = filterOutInvisibleTypes tc args          typats          = map (synifyType WithinType []) args_types_only -        annot_typats    = zipWith3 annotHsType (mkIsPolyTvs fam_tvs) -                                   args_types_only typats +        annot_typats    = zipWith3 annotHsType args_poly args_types_only typats          hs_rhs          = synifyType WithinType [] rhs          outer_bndrs     = HsOuterImplicit{hso_ximplicit = map tyVarName tkvs}                                         -- TODO: this must change eventually @@ -179,7 +177,7 @@ synifyAxBranch tc (CoAxBranch { cab_tvs = tkvs, cab_lhs = args, cab_rhs = rhs })                , feqn_fixity = synifyFixity name                , feqn_rhs    = hs_rhs }    where -    fam_tvs = tyConVisibleTyVars tc +    args_poly = tyConArgsPolyKinded tc  synifyAxiom :: CoAxiom br -> Either ErrMsg (HsDecl GhcRn)  synifyAxiom ax@(CoAxiom { co_ax_tc = tc }) @@ -506,17 +504,26 @@ annotHsType True ty hs_ty      in noLoc (HsKindSig noExtField hs_ty hs_ki)  annotHsType _    _ hs_ty = hs_ty --- | For every type variable in the input, --- report whether or not the tv is poly-kinded. This is used to eventually --- feed into 'annotHsType'. -mkIsPolyTvs :: [TyVar] -> [Bool] -mkIsPolyTvs = map is_poly_tv +-- | For every argument type that a type constructor accepts, +-- report whether or not the argument is poly-kinded. This is used to +-- eventually feed into 'annotThType'. +tyConArgsPolyKinded :: TyCon -> [Bool] +tyConArgsPolyKinded tc = +     map (is_poly_ty . tyVarKind)      tc_vis_tvs +  ++ map (is_poly_ty . tyCoBinderType) tc_res_kind_vis_bndrs +  ++ repeat True    where -    is_poly_tv tv = not $ +    is_poly_ty :: Type -> Bool +    is_poly_ty ty = not $                      isEmptyVarSet $                      filterVarSet isTyVar $ -                    tyCoVarsOfType $ -                    tyVarKind tv +                    tyCoVarsOfType ty + +    tc_vis_tvs :: [TyVar] +    tc_vis_tvs = tyConVisibleTyVars tc + +    tc_res_kind_vis_bndrs :: [TyCoBinder] +    tc_res_kind_vis_bndrs = filter isVisibleBinder $ fst $ splitPiTys $ tyConResKind tc  --states of what to do with foralls:  data SynifyTypeState @@ -641,11 +648,14 @@ synifyType _ vs (TyConApp tc tys)          in noLoc $ HsKindSig noExtField ty' full_kind'        | otherwise = ty' -synifyType s vs (AppTy t1 (CoercionTy {})) = synifyType s vs t1 -synifyType _ vs (AppTy t1 t2) = let -  s1 = synifyType WithinType vs t1 -  s2 = synifyType WithinType vs t2 -  in noLoc $ HsAppTy noExtField s1 s2 +synifyType _ vs ty@(AppTy {}) = let +  (ty_head, ty_args) = splitAppTys ty +  ty_head' = synifyType WithinType vs ty_head +  ty_args' = map (synifyType WithinType vs) $ +             filterOut isCoercionTy $ +             filterByList (map isVisibleArgFlag $ appTyArgFlags ty_head ty_args) +                          ty_args +  in foldl (\t1 t2 -> noLoc $ HsAppTy noExtField t1 t2) ty_head' ty_args'  synifyType s vs funty@(FunTy InvisArg _ _ _) = synifySigmaType s vs funty  synifyType _ vs       (FunTy VisArg w t1 t2) = let    s1 = synifyType WithinType vs t1 @@ -838,8 +848,8 @@ synifyInstHead (vs, preds, cls, types) = specializeInstHead $ InstHead      cls_tycon = classTyCon cls      ts  = filterOutInvisibleTypes cls_tycon types      ts' = map (synifyType WithinType vs) ts -    annot_ts = zipWith3 annotHsType is_poly_tvs ts ts' -    is_poly_tvs = mkIsPolyTvs (tyConVisibleTyVars cls_tycon) +    annot_ts = zipWith3 annotHsType args_poly ts ts' +    args_poly = tyConArgsPolyKinded cls_tycon      synifyClsIdSig = synifyIdSig ShowRuntimeRep DeleteTopLevelQuantification vs  -- Convert a family instance, this could be a type family or data family @@ -878,8 +888,8 @@ synifyFamInst fi opaque = do      ts = filterOutInvisibleTypes fam_tc eta_expanded_lhs      synifyTypes = map (synifyType WithinType [])      ts' = synifyTypes ts -    annot_ts = zipWith3 annotHsType is_poly_tvs ts ts' -    is_poly_tvs = mkIsPolyTvs (tyConVisibleTyVars fam_tc) +    annot_ts = zipWith3 annotHsType args_poly ts ts' +    args_poly = tyConArgsPolyKinded fam_tc  {-  Note [Invariant: Never expand type synonyms] diff --git a/haddock-api/src/Haddock/GhcUtils.hs b/haddock-api/src/Haddock/GhcUtils.hs index b7e2cafa..546e2941 100644 --- a/haddock-api/src/Haddock/GhcUtils.hs +++ b/haddock-api/src/Haddock/GhcUtils.hs @@ -24,6 +24,7 @@ module Haddock.GhcUtils where  import Control.Arrow  import Data.Char ( isSpace ) +import Data.Maybe ( mapMaybe )  import Haddock.Types( DocName, DocNameI ) @@ -35,6 +36,7 @@ import GHC.Types.Name  import GHC.Unit.Module  import GHC  import GHC.Driver.Session +import GHC.Types.Basic  import GHC.Types.SrcLoc  ( advanceSrcLoc )  import GHC.Types.Var     ( Specificity, VarBndr(..), TyVarBinder                           , tyVarKind, updateTyVarKind, isInvisibleArgFlag ) @@ -112,6 +114,12 @@ pretty = showPpr  -- These functions are duplicated from the GHC API, as they must be  -- instantiated at DocNameI instead of (GhcPass _). +-- | Like 'hsTyVarName' from GHC API, but not instantiated at (GhcPass _) +hsTyVarBndrName :: forall flag n. (XXTyVarBndr n ~ NoExtCon, UnXRec n) +                => HsTyVarBndr flag n -> IdP n +hsTyVarBndrName (UserTyVar _ _ name) = unXRec @n name +hsTyVarBndrName (KindedTyVar _ _ name _) = unXRec @n name +  hsTyVarNameI :: HsTyVarBndr flag DocNameI -> DocName  hsTyVarNameI (UserTyVar _ _ (L _ n))     = n  hsTyVarNameI (KindedTyVar _ _ (L _ n) _) = n @@ -123,6 +131,23 @@ getConNamesI :: ConDecl DocNameI -> [Located DocName]  getConNamesI ConDeclH98  {con_name  = name}  = [name]  getConNamesI ConDeclGADT {con_names = names} = names +hsSigTypeI :: LHsSigType DocNameI -> LHsType DocNameI +hsSigTypeI = sig_body . unLoc + +mkEmptySigType :: LHsType GhcRn -> LHsSigType GhcRn +-- Dubious, because the implicit binders are empty even +-- though the type might have free varaiables +mkEmptySigType lty@(L loc ty) = L loc $ case ty of +  HsForAllTy { hst_tele = HsForAllInvis { hsf_invis_bndrs = bndrs } +             , hst_body = body } +    -> HsSig { sig_ext = noExtField +             , sig_bndrs = HsOuterExplicit { hso_xexplicit = noExtField +                                           , hso_bndrs     = bndrs } +             , sig_body = body } +  _ -> HsSig { sig_ext   = noExtField +             , sig_bndrs = HsOuterImplicit{hso_ximplicit = []} +             , sig_body = lty } +  mkHsForAllInvisTeleI ::    [LHsTyVarBndr Specificity DocNameI] -> HsForAllTelescope DocNameI  mkHsForAllInvisTeleI invis_bndrs = @@ -184,6 +209,99 @@ tyClDeclLNameI (ClassDecl { tcdLName = ln }) = ln  tcdNameI :: TyClDecl DocNameI -> DocName  tcdNameI = unLoc . tyClDeclLNameI +addClassContext :: Name -> LHsQTyVars GhcRn -> LSig GhcRn -> LSig GhcRn +-- Add the class context to a class-op signature +addClassContext cls tvs0 (L pos (ClassOpSig _ _ lname ltype)) +  = L pos (TypeSig noExtField lname (mkEmptyWildCardBndrs (go_sig_ty ltype))) +  where +    go_sig_ty (L loc (HsSig { sig_bndrs = bndrs, sig_body = ty })) +       = L loc (HsSig { sig_ext = noExtField +                      , sig_bndrs = bndrs, sig_body = go_ty ty }) + +    go_ty (L loc (HsForAllTy { hst_tele = tele, hst_body = ty })) +       = L loc (HsForAllTy { hst_xforall = noExtField +                           , hst_tele = tele, hst_body = go_ty ty }) +    go_ty (L loc (HsQualTy { hst_ctxt = ctxt, hst_body = ty })) +       = L loc (HsQualTy { hst_xqual = noExtField +                         , hst_ctxt = add_ctxt ctxt, hst_body = ty }) +    go_ty (L loc ty) +       = L loc (HsQualTy { hst_xqual = noExtField +                         , hst_ctxt = add_ctxt (L loc []), hst_body = L loc ty }) + +    extra_pred = nlHsTyConApp Prefix cls (lHsQTyVarsToTypes tvs0) +    add_ctxt (L loc preds) = L loc (extra_pred : preds) + +addClassContext _ _ sig = sig   -- E.g. a MinimalSig is fine + +lHsQTyVarsToTypes :: LHsQTyVars GhcRn -> [LHsTypeArg GhcRn] +lHsQTyVarsToTypes tvs +  = [ HsValArg $ noLoc (HsTyVar noExtField NotPromoted (noLoc (hsLTyVarName tv))) +    | tv <- hsQTvExplicit tvs ] + + +-------------------------------------------------------------------------------- +-- * Making abstract declarations +-------------------------------------------------------------------------------- + +restrictTo :: [Name] -> LHsDecl GhcRn -> LHsDecl GhcRn +restrictTo names (L loc decl) = L loc $ case decl of +  TyClD x d | isDataDecl d  -> +    TyClD x (d { tcdDataDefn = restrictDataDefn names (tcdDataDefn d) }) +  TyClD x d | isClassDecl d -> +    TyClD x (d { tcdSigs = restrictDecls names (tcdSigs d), +               tcdATs = restrictATs names (tcdATs d) }) +  _ -> decl + +restrictDataDefn :: [Name] -> HsDataDefn GhcRn -> HsDataDefn GhcRn +restrictDataDefn names defn@(HsDataDefn { dd_ND = new_or_data, dd_cons = cons }) +  | DataType <- new_or_data +  = defn { dd_cons = restrictCons names cons } +  | otherwise    -- Newtype +  = case restrictCons names cons of +      []    -> defn { dd_ND = DataType, dd_cons = [] } +      [con] -> defn { dd_cons = [con] } +      _ -> error "Should not happen" + +restrictCons :: [Name] -> [LConDecl GhcRn] -> [LConDecl GhcRn] +restrictCons names decls = [ L p d | L p (Just d) <- map (fmap keep) decls ] +  where +    keep :: ConDecl GhcRn -> Maybe (ConDecl GhcRn) +    keep d +      | any (\n -> n `elem` names) (map unLoc $ getConNames d) = +        case d of +          ConDeclH98 { con_args = con_args' } -> case con_args' of +            PrefixCon {} -> Just d +            RecCon fields +              | all field_avail (unLoc fields) -> Just d +              | otherwise -> Just (d { con_args = PrefixCon [] (field_types $ unLoc fields) }) +              -- if we have *all* the field names available, then +              -- keep the record declaration.  Otherwise degrade to +              -- a constructor declaration.  This isn't quite right, but +              -- it's the best we can do. +            InfixCon _ _ -> Just d + +          ConDeclGADT { con_g_args = con_args' } -> case con_args' of +            PrefixConGADT {} -> Just d +            RecConGADT fields +              | all field_avail (unLoc fields) -> Just d +              | otherwise -> Just (d { con_g_args = PrefixConGADT (field_types $ unLoc fields) }) +              -- see above +      where +        field_avail :: LConDeclField GhcRn -> Bool +        field_avail (L _ (ConDeclField _ fs _ _)) +            = all (\f -> extFieldOcc (unLoc f) `elem` names) fs + +        field_types flds = [ hsUnrestricted t | L _ (ConDeclField _ _ t _) <- flds ] + +    keep _ = Nothing + +restrictDecls :: [Name] -> [LSig GhcRn] -> [LSig GhcRn] +restrictDecls names = mapMaybe (filterLSigNames (`elem` names)) + + +restrictATs :: [Name] -> [LFamilyDecl GhcRn] -> [LFamilyDecl GhcRn] +restrictATs names ats = [ at | at <- ats , unLoc (fdLName (unLoc at)) `elem` names ] +  -------------------------------------------------------------------------------  -- * Parenthesization @@ -193,6 +311,8 @@ tcdNameI = unLoc . tyClDeclLNameI  data Precedence    = PREC_TOP  -- ^ precedence of 'type' production in GHC's parser +  | PREC_SIG  -- ^ explicit type signature +    | PREC_CTX  -- ^ Used for single contexts, eg. ctx => type                -- (as opposed to (ctx1, ctx2) => type) @@ -221,18 +341,22 @@ reparenTypePrec = go    go _ (HsBangTy x b ty)     = HsBangTy x b (reparenLType ty)    go _ (HsTupleTy x con tys) = HsTupleTy x con (map reparenLType tys)    go _ (HsSumTy x tys)       = HsSumTy x (map reparenLType tys) -  go _ (HsKindSig x ty kind) = HsKindSig x (reparenLType ty) (reparenLType kind)    go _ (HsListTy x ty)       = HsListTy x (reparenLType ty)    go _ (HsRecTy x flds)      = HsRecTy x (map (mapXRec @a reparenConDeclField) flds)    go p (HsDocTy x ty d)      = HsDocTy x (goL p ty) d    go _ (HsExplicitListTy x p tys) = HsExplicitListTy x p (map reparenLType tys)    go _ (HsExplicitTupleTy x tys) = HsExplicitTupleTy x (map reparenLType tys) +  go p (HsKindSig x ty kind) +    = paren p PREC_SIG $ HsKindSig x (goL PREC_SIG ty) (goL PREC_SIG kind)    go p (HsIParamTy x n ty) -    = paren p PREC_CTX $ HsIParamTy x n (reparenLType ty) +    = paren p PREC_SIG $ HsIParamTy x n (reparenLType ty)    go p (HsForAllTy x tele ty)      = paren p PREC_CTX $ HsForAllTy x (reparenHsForAllTelescope tele) (reparenLType ty)    go p (HsQualTy x ctxt ty) -    = paren p PREC_FUN $ HsQualTy x (mapXRec @a (map reparenLType) ctxt) (reparenLType ty) +    = let p' [_] = PREC_CTX +          p' _   = PREC_TOP -- parens will get added anyways later... +          ctxt' = mapXRec @a (\xs -> map (goL (p' xs)) xs) ctxt +      in paren p PREC_CTX $ HsQualTy x ctxt' (goL PREC_TOP ty)    go p (HsFunTy x w ty1 ty2)      = paren p PREC_FUN $ HsFunTy x w (goL PREC_FUN ty1) (goL PREC_TOP ty2)    go p (HsAppTy x fun_ty arg_ty) @@ -347,18 +471,17 @@ class Parent a where  instance Parent (ConDecl GhcRn) where    children con = -    case con_args con of -      RecCon fields -> map (extFieldOcc . unL) $ -                         concatMap (cd_fld_names . unL) (unL fields) -      _             -> [] +    case getRecConArgs_maybe con of +      Nothing -> [] +      Just flds -> map (extFieldOcc . unLoc) $ concatMap (cd_fld_names . unLoc) (unLoc flds)  instance Parent (TyClDecl GhcRn) where    children d -    | isDataDecl  d = map unL $ concatMap (getConNames . unL) +    | isDataDecl  d = map unLoc $ concatMap (getConNames . unLoc)                                $ (dd_cons . tcdDataDefn) $ d      | isClassDecl d = -        map (unL . fdLName . unL) (tcdATs d) ++ -        [ unL n | L _ (TypeSig _ ns _) <- tcdSigs d, n <- ns ] +        map (unLoc . fdLName . unLoc) (tcdATs d) ++ +        [ unLoc n | L _ (TypeSig _ ns _) <- tcdSigs d, n <- ns ]      | otherwise = [] @@ -368,13 +491,13 @@ family = getName &&& children  familyConDecl :: ConDecl GHC.GhcRn -> [(Name, [Name])] -familyConDecl d = zip (map unL (getConNames d)) (repeat $ children d) +familyConDecl d = zip (map unLoc (getConNames d)) (repeat $ children d)  -- | A mapping from the parent (main-binder) to its children and from each  -- child to its grand-children, recursively.  families :: TyClDecl GhcRn -> [(Name, [Name])]  families d -  | isDataDecl  d = family d : concatMap (familyConDecl . unL) (dd_cons (tcdDataDefn d)) +  | isDataDecl  d = family d : concatMap (familyConDecl . unLoc) (dd_cons (tcdDataDefn d))    | isClassDecl d = [family d]    | otherwise     = [] @@ -406,17 +529,16 @@ modifySessionDynFlags f = do  -- * DynFlags  ------------------------------------------------------------------------------- - -setObjectDir, setHiDir, setHieDir, setStubDir, setOutputDir :: String -> DynFlags -> DynFlags -setObjectDir  f d = d{ objectDir  = Just f} -setHiDir      f d = d{ hiDir      = Just f} -setHieDir     f d = d{ hieDir     = Just f} -setStubDir    f d = d{ stubDir    = Just f -                     , includePaths = addGlobalInclude (includePaths d) [f] } -  -- -stubdir D adds an implicit -I D, so that gcc can find the _stub.h file -  -- \#included from the .hc file when compiling with -fvia-C. -setOutputDir  f = setObjectDir f . setHiDir f . setHieDir f . setStubDir f - +-- TODO: use `setOutputDir` from GHC +setOutputDir :: FilePath -> DynFlags -> DynFlags +setOutputDir dir dynFlags = +  dynFlags { objectDir    = Just dir +           , hiDir        = Just dir +           , hieDir       = Just dir +           , stubDir      = Just dir +           , includePaths = addGlobalInclude (includePaths dynFlags) [dir] +           , dumpDir      = Just dir +           }  -------------------------------------------------------------------------------  -- * 'StringBuffer' and 'ByteString' diff --git a/haddock-api/src/Haddock/Interface.hs b/haddock-api/src/Haddock/Interface.hs index c557968f..fa1f3ee5 100644 --- a/haddock-api/src/Haddock/Interface.hs +++ b/haddock-api/src/Haddock/Interface.hs @@ -44,11 +44,11 @@ import Haddock.Types  import Haddock.Utils  import Control.Monad +import Control.Monad.IO.Class ( MonadIO, liftIO )  import Data.IORef -import Data.List +import Data.List (foldl', isPrefixOf, nub)  import qualified Data.Map as Map  import qualified Data.Set as Set -import Distribution.Verbosity  import Text.Printf  import GHC.Unit.Module.Env (mkModuleSet, emptyModuleSet, unionModuleSet, ModuleSet) @@ -69,6 +69,7 @@ import GHC.Types.Name.Occurrence (isTcOcc)  import GHC.Types.Name.Reader (unQualOK, greMangledName, globalRdrEnvElts)  import GHC.Utils.Error (withTimingD)  import GHC.HsToCore.Docs +import GHC.Runtime.Loader (initializePlugins)  import GHC.Plugins (Outputable, StaticPlugin(..), Plugin(..), PluginWithArgs(..),                       defaultPlugin, keepRenamedSource) @@ -126,7 +127,7 @@ processModules verbosity modules flags extIfaces = do    let warnings = Flag_NoWarnings `notElem` flags    dflags <- getDynFlags    let (interfaces'', msgs) = -         runWriter $ mapM (renameInterface dflags links warnings) interfaces' +         runWriter $ mapM (renameInterface dflags (ignoredSymbols flags) links warnings) interfaces'    liftIO $ mapM_ putStrLn msgs    return (interfaces'', homeLinks) @@ -364,3 +365,4 @@ buildHomeLinks ifaces = foldl upd Map.empty (reverse ifaces)          mdl            = ifaceMod iface          keep_old env n = Map.insertWith (\_ old -> old) n mdl env          keep_new env n = Map.insert n mdl env + diff --git a/haddock-api/src/Haddock/Interface/AttachInstances.hs b/haddock-api/src/Haddock/Interface/AttachInstances.hs index 0d3f1ab5..6ef0ed19 100644 --- a/haddock-api/src/Haddock/Interface/AttachInstances.hs +++ b/haddock-api/src/Haddock/Interface/AttachInstances.hs @@ -22,7 +22,7 @@ import Haddock.Convert  import Control.Applicative ((<|>))  import Control.Arrow hiding ((<+>)) -import Data.List +import Data.List (sortBy)  import Data.Ord (comparing)  import Data.Maybe ( maybeToList, mapMaybe, fromMaybe )  import qualified Data.Map as Map diff --git a/haddock-api/src/Haddock/Interface/Create.hs b/haddock-api/src/Haddock/Interface/Create.hs index 76f1f765..72f1ab62 100644 --- a/haddock-api/src/Haddock/Interface/Create.hs +++ b/haddock-api/src/Haddock/Interface/Create.hs @@ -1,4 +1,4 @@ -{-# LANGUAGE StandaloneDeriving, FlexibleInstances, MultiParamTypeClasses, CPP, TupleSections, BangPatterns, LambdaCase, NamedFieldPuns, ScopedTypeVariables #-} +{-# LANGUAGE StandaloneDeriving, FlexibleInstances, MultiParamTypeClasses, CPP, TupleSections, BangPatterns, LambdaCase, NamedFieldPuns, ScopedTypeVariables, RecordWildCards #-}  {-# LANGUAGE TypeFamilies #-}  {-# LANGUAGE ViewPatterns #-}  {-# LANGUAGE DerivingStrategies #-} @@ -38,6 +38,7 @@ import Data.Map (Map)  import Data.List  import Data.Maybe  import Data.Traversable +import GHC.Stack  import GHC.Tc.Utils.Monad (finalSafeMode)  import GHC.Types.Avail hiding (avail) @@ -65,7 +66,6 @@ import GHC.HsToCore.Docs hiding (mkMaps)  import GHC.Parser.Annotation (IsUnicodeSyntax(..))  import GHC.Unit.Module.Warnings -  newtype IfEnv m = IfEnv    {      -- | Lookup names in the enviroment. @@ -687,11 +687,11 @@ availExportItem is_sig modMap thisMod semMod warnings exportedNames                      let newDecl = L loc . SigD noExtField . fromJust $ filterSigNames (== t) sig                      in availExportDecl avail newDecl docs_ -                  L loc (TyClD _ cl@ClassDecl{}) -> do +                  L loc (TyClD _ ClassDecl {..}) -> do                      mdef <- minimalDef t                      let sig = maybeToList $ fmap (noLoc . MinimalSig noExtField NoSourceText . noLoc . fmap noLoc) mdef                      availExportDecl avail -                      (L loc $ TyClD noExtField cl { tcdSigs = sig ++ tcdSigs cl }) docs_ +                      (L loc $ TyClD noExtField ClassDecl { tcdSigs = sig ++ tcdSigs, .. }) docs_                    _ -> availExportDecl avail decl docs_ @@ -716,11 +716,24 @@ availExportItem is_sig modMap thisMod semMod warnings exportedNames          _ -> return [] -    availExportDecl :: AvailInfo -> LHsDecl GhcRn +    -- Tries 'extractDecl' first then falls back to 'hiDecl' if that fails +    availDecl :: Name -> LHsDecl GhcRn -> IfM m (LHsDecl GhcRn) +    availDecl declName parentDecl = +      case extractDecl declMap declName parentDecl of +        Right d -> pure d +        Left err -> do +          synifiedDeclOpt <- hiDecl dflags declName +          case synifiedDeclOpt of +            Just synifiedDecl -> pure synifiedDecl +            Nothing -> pprPanic "availExportItem" (O.text err) + +    availExportDecl :: HasCallStack => AvailInfo -> LHsDecl GhcRn                      -> (DocForDecl Name, [(Name, DocForDecl Name)])                      -> IfM m [ ExportItem GhcRn ]      availExportDecl avail decl (doc, subs)        | availExportsDecl avail = do +          extractedDecl <- availDecl (availName avail) decl +            -- bundled pattern synonyms only make sense if the declaration is            -- exported (otherwise there would be nothing to bundle to)            bundledPatSyns <- findBundledPatterns avail @@ -736,8 +749,7 @@ availExportItem is_sig modMap thisMod semMod warnings exportedNames                  ]            return [ ExportDecl { -                       expItemDecl      = restrictTo (fmap fst subs) -                                            (extractDecl declMap (availName avail) decl) +                       expItemDecl      = restrictTo (fmap fst subs) extractedDecl                       , expItemPats      = bundledPatSyns                       , expItemMbDoc     = doc                       , expItemSubDocs   = subs @@ -747,18 +759,18 @@ availExportItem is_sig modMap thisMod semMod warnings exportedNames                       }                   ] -      | otherwise = -          return [ ExportDecl { -                       expItemDecl      = extractDecl declMap sub decl +      | otherwise = for subs $ \(sub, sub_doc) -> do +          extractedDecl <- availDecl sub decl + +          return ( ExportDecl { +                       expItemDecl      = extractedDecl                       , expItemPats      = []                       , expItemMbDoc     = sub_doc                       , expItemSubDocs   = []                       , expItemInstances = []                       , expItemFixities  = [ (sub, f) | Just f <- [M.lookup sub fixMap] ]                       , expItemSpliced   = False -                     } -                 | (sub, sub_doc) <- subs -                 ] +                     } )      exportedNameSet = mkNameSet exportedNames      isExported n = elemNameSet n exportedNameSet @@ -975,16 +987,26 @@ fullModuleContents is_sig modMap pkgName thisMod semMod warnings gre exportedNam  -- it might be an individual record selector or a class method.  In these  -- cases we have to extract the required declaration (and somehow cobble  -- together a type signature for it...). -extractDecl :: DeclMap -> Name -> LHsDecl GhcRn -> LHsDecl GhcRn +-- +-- This function looks through the declarations in this module to try to find +-- the one with the right name. +extractDecl +  :: HasCallStack +  => DeclMap                   -- ^ all declarations in the file +  -> Name                      -- ^ name of the declaration to extract +  -> LHsDecl GhcRn             -- ^ parent declaration +  -> Either ErrMsg (LHsDecl GhcRn)  extractDecl declMap name decl -  | name `elem` getMainDeclBinder (unLoc decl) = decl +  | name `elem` getMainDeclBinder (unLoc decl) = pure decl    | otherwise  =      case unLoc decl of -      TyClD _ d@ClassDecl {} -> +      TyClD _ d@ClassDecl { tcdLName = L _ clsNm +                          , tcdSigs = clsSigs +                          , tcdATs = clsATs } ->          let            matchesMethod =              [ lsig -            | lsig <- tcdSigs d +            | lsig <- clsSigs              , ClassOpSig _ False _ _ <- pure $ unLoc lsig                -- Note: exclude `default` declarations (see #505)              , name `elem` sigName lsig @@ -992,29 +1014,31 @@ extractDecl declMap name decl            matchesAssociatedType =              [ lfam_decl -            | lfam_decl <- tcdATs d +            | lfam_decl <- clsATs              , name == unLoc (fdLName (unLoc lfam_decl))              ]              -- TODO: document fixity          in case (matchesMethod, matchesAssociatedType)  of -          ([s0], _) -> let (n, tyvar_names) = (tcdName d, tyClDeclTyVars d) -                           L pos sig = addClassContext n tyvar_names s0 -                       in L pos (SigD noExtField sig) -          (_, [L pos fam_decl]) -> L pos (TyClD noExtField (FamDecl noExtField fam_decl)) +          ([s0], _) -> let tyvar_names = tyClDeclTyVars d +                           L pos sig = addClassContext clsNm tyvar_names s0 +                       in pure (L pos (SigD noExtField sig)) +          (_, [L pos fam_decl]) -> pure (L pos (TyClD noExtField (FamDecl noExtField fam_decl)))            ([], [])              | Just (famInstDecl:_) <- M.lookup name declMap              -> extractDecl declMap name famInstDecl -          _ -> pprPanic "extractDecl" (O.text "Ambiguous decl for" O.<+> O.ppr name O.<+> O.text "in class:" -                                         O.$$ O.nest 4 (O.ppr d) -                                         O.$$ O.text "Matches:" -                                         O.$$ O.nest 4 (O.ppr matchesMethod O.<+> O.ppr matchesAssociatedType)) -      TyClD _ d@DataDecl {} -> -        let (n, tyvar_tys) = (tcdName d, lHsQTyVarsToTypes (tyClDeclTyVars d)) -        in if isDataConName name -           then SigD noExtField <$> extractPatternSyn name n tyvar_tys (dd_cons (tcdDataDefn d)) -           else SigD noExtField <$> extractRecSel name n tyvar_tys (dd_cons (tcdDataDefn d)) +          _ -> Left (concat [ "Ambiguous decl for ", getOccString name +                            , " in class ", getOccString clsNm ]) + +      TyClD _ d@DataDecl { tcdLName = L _ dataNm +                         , tcdDataDefn = HsDataDefn { dd_cons = dataCons } } -> do +        let ty_args = lHsQTyVarsToTypes (tyClDeclTyVars d) +        lsig <- if isDataConName name +                  then extractPatternSyn name dataNm ty_args dataCons +                  else extractRecSel name dataNm ty_args dataCons +        pure (SigD noExtField <$> lsig) +        TyClD _ FamDecl {}          | isValName name          , Just (famInst:_) <- M.lookup name declMap @@ -1024,8 +1048,8 @@ extractDecl declMap name decl                                      , feqn_pats  = tys                                      , feqn_rhs   = defn }))) ->          if isDataConName name -        then SigD noExtField <$> extractPatternSyn name n tys (dd_cons defn) -        else SigD noExtField <$> extractRecSel name n tys (dd_cons defn) +        then fmap (SigD noExtField) <$> extractPatternSyn name n tys (dd_cons defn) +        else fmap (SigD noExtField) <$> extractRecSel name n tys (dd_cons defn)        InstD _ (ClsInstD _ ClsInstDecl { cid_datafam_insts = insts })          | isDataConName name ->              let matches = [ d' | L _ d'@(DataFamInstDecl (FamEqn { feqn_rhs = dd })) <- insts @@ -1033,9 +1057,9 @@ extractDecl declMap name decl                                 ]              in case matches of                  [d0] -> extractDecl declMap name (noLoc (InstD noExtField (DataFamInstD noExtField d0))) -                _    -> error "internal: extractDecl (ClsInstD)" +                _    -> Left "internal: extractDecl (ClsInstD)"          | otherwise -> -            let matches = [ d' | L _ d'@(DataFamInstDecl d) +            let matches = [ d' | L _ d'@(DataFamInstDecl d )                                     <- insts                                   -- , L _ ConDecl { con_details = RecCon rec } <- dd_cons (feqn_rhs d)                                 , Just rec <- map (getRecConArgs_maybe . unLoc) (dd_cons (feqn_rhs d)) @@ -1045,16 +1069,18 @@ extractDecl declMap name decl                            ]              in case matches of                [d0] -> extractDecl declMap name (noLoc . InstD noExtField $ DataFamInstD noExtField d0) -              _ -> error "internal: extractDecl (ClsInstD)" -      _ -> pprPanic "extractDecl" $ -        O.text "Unhandled decl for" O.<+> O.ppr name O.<> O.text ":" -        O.$$ O.nest 4 (O.ppr decl) +              _ -> Left "internal: extractDecl (ClsInstD)" +      _ -> Left ("extractDecl: Unhandled decl for " ++ getOccString name) -extractPatternSyn :: Name -> Name -> [LHsTypeArg GhcRn] -> [LConDecl GhcRn] -> LSig GhcRn +extractPatternSyn :: HasCallStack +                  => Name -> Name +                  -> [LHsTypeArg GhcRn] -> [LConDecl GhcRn] +                  -> Either ErrMsg (LSig GhcRn)  extractPatternSyn nm t tvs cons =    case filter matches cons of -    [] -> error "extractPatternSyn: constructor pattern not found" -    con:_ -> extract <$> con +    [] -> Left . O.showSDocOneLine O.defaultSDocContext $ +          O.text "constructor pattern " O.<+> O.ppr nm O.<+> O.text "not found in type" O.<+> O.ppr t +    con:_ -> pure (extract <$> con)   where    matches :: LConDecl GhcRn -> Bool    matches (L _ con) = nm `elem` (unLoc <$> getConNames con) @@ -1089,13 +1115,13 @@ extractPatternSyn nm t tvs cons =                            mkAppTyArg f (HsArgPar _) = HsParTy noExtField f  extractRecSel :: Name -> Name -> [LHsTypeArg GhcRn] -> [LConDecl GhcRn] -              -> LSig GhcRn -extractRecSel _ _ _ [] = error "extractRecSel: selector not found" +              -> Either ErrMsg (LSig GhcRn) +extractRecSel _ _ _ [] = Left "extractRecSel: selector not found"  extractRecSel nm t tvs (L _ con : rest) =    case getRecConArgs_maybe con of      Just (L _ fields) | ((l,L _ (ConDeclField _ _nn ty _)) : _) <- matching_fields fields -> -      L l (TypeSig noExtField [noLoc nm] (mkEmptySigWcType (noLoc (HsFunTy noExtField (HsUnrestrictedArrow NormalSyntax) data_ty (getBangType ty))))) +      pure (L l (TypeSig noExtField [noLoc nm] (mkEmptyWildCardBndrs $ mkEmptySigType (noLoc (HsFunTy noExtField (HsUnrestrictedArrow NormalSyntax) data_ty (getBangType ty))))))      _ -> extractRecSel nm t tvs rest   where    matching_fields :: [LConDeclField GhcRn] -> [(SrcSpan, LConDeclField GhcRn)] diff --git a/haddock-api/src/Haddock/Interface/Json.hs b/haddock-api/src/Haddock/Interface/Json.hs index df585f29..9b80d98f 100644 --- a/haddock-api/src/Haddock/Interface/Json.hs +++ b/haddock-api/src/Haddock/Interface/Json.hs @@ -13,7 +13,6 @@ import GHC.Utils.Outputable  import Control.Arrow  import Data.Map (Map) -import Data.Bifunctor  import qualified Data.Map as Map  import Haddock.Types @@ -58,11 +57,172 @@ jsonMap f g = jsonObject . map (f *** g) . Map.toList  jsonMDoc :: MDoc Name -> JsonDoc  jsonMDoc MetaDoc{..} =    jsonObject [ ("meta", jsonObject [("version", jsonMaybe (jsonString . show) (_version _meta))]) -             , ("doc",  jsonDoc _doc) +             , ("document",  jsonDoc _doc)               ] +showModName :: Wrap (ModuleName, OccName) -> String +showModName = showWrapped (moduleNameString . fst) + +showName :: Wrap Name -> String +showName = showWrapped nameStableString + +  jsonDoc :: Doc Name -> JsonDoc -jsonDoc doc = jsonString (show (bimap (moduleNameString . fst) nameStableString doc)) + +jsonDoc DocEmpty = jsonObject +    [ ("tag", jsonString "DocEmpty") ] + +jsonDoc (DocAppend x y) = jsonObject +    [ ("tag", jsonString "DocAppend") +    , ("first", jsonDoc x) +    , ("second", jsonDoc y) +    ] + +jsonDoc (DocString s) = jsonObject +    [ ("tag", jsonString "DocString") +    , ("string", jsonString s) +    ] + +jsonDoc (DocParagraph x) = jsonObject +    [ ("tag", jsonString "DocParagraph") +    , ("document", jsonDoc x) +    ] + +jsonDoc (DocIdentifier name) = jsonObject +    [ ("tag", jsonString "DocIdentifier") +    , ("name", jsonString (showName name)) +    ] + +jsonDoc (DocIdentifierUnchecked modName) = jsonObject +    [ ("tag", jsonString "DocIdentifierUnchecked") +    , ("modName", jsonString (showModName modName)) +    ] + +jsonDoc (DocModule s) = jsonObject +    [ ("tag", jsonString "DocModule") +    , ("string", jsonString s) +    ] + +jsonDoc (DocWarning x) = jsonObject +    [ ("tag", jsonString "DocWarning") +    , ("document", jsonDoc x) +    ] + +jsonDoc (DocEmphasis x) = jsonObject +    [ ("tag", jsonString "DocEmphasis") +    , ("document", jsonDoc x) +    ] + +jsonDoc (DocMonospaced x) = jsonObject +    [ ("tag", jsonString "DocMonospaced") +    , ("document", jsonDoc x) +    ] + +jsonDoc (DocBold x) = jsonObject +    [ ("tag", jsonString "DocBold") +    , ("document", jsonDoc x) +    ] + +jsonDoc (DocUnorderedList xs) = jsonObject +    [ ("tag", jsonString "DocUnorderedList") +    , ("documents", jsonArray (fmap jsonDoc xs)) +    ] + +jsonDoc (DocOrderedList xs) = jsonObject +    [ ("tag", jsonString "DocOrderedList") +    , ("documents", jsonArray (fmap jsonDoc xs)) +    ] + +jsonDoc (DocDefList xys) = jsonObject +    [ ("tag", jsonString "DocDefList") +    , ("definitions", jsonArray (fmap jsonDef xys)) +    ] +  where +    jsonDef (x, y) = jsonObject [("document", jsonDoc x), ("y", jsonDoc y)] + +jsonDoc (DocCodeBlock x) = jsonObject +    [ ("tag", jsonString "DocCodeBlock") +    , ("document", jsonDoc x) +    ] + +jsonDoc (DocHyperlink hyperlink) = jsonObject +    [ ("tag", jsonString "DocHyperlink") +    , ("hyperlink", jsonHyperlink hyperlink) +    ] +  where +    jsonHyperlink Hyperlink{..} = jsonObject +        [ ("hyperlinkUrl", jsonString hyperlinkUrl) +        , ("hyperlinkLabel", jsonMaybe jsonDoc hyperlinkLabel) +        ] + +jsonDoc (DocPic picture) = jsonObject +    [ ("tag", jsonString "DocPic") +    , ("picture", jsonPicture picture) +    ] +  where +    jsonPicture Picture{..} = jsonObject +        [ ("pictureUrl", jsonString pictureUri) +        , ("pictureLabel", jsonMaybe jsonString pictureTitle) +        ] + +jsonDoc (DocMathInline s) = jsonObject +    [ ("tag", jsonString "DocMathInline") +    , ("string", jsonString s) +    ] + +jsonDoc (DocMathDisplay s) = jsonObject +    [ ("tag", jsonString "DocMathDisplay") +    , ("string", jsonString s) +    ] + +jsonDoc (DocAName s) = jsonObject +    [ ("tag", jsonString "DocAName") +    , ("string", jsonString s) +    ] + +jsonDoc (DocProperty s) = jsonObject +    [ ("tag", jsonString "DocProperty") +    , ("string", jsonString s) +    ] + +jsonDoc (DocExamples examples) = jsonObject +    [ ("tag", jsonString "DocExamples") +    , ("examples", jsonArray (fmap jsonExample examples)) +    ] +  where +    jsonExample Example{..} = jsonObject +        [ ("exampleExpression", jsonString exampleExpression) +        , ("exampleResult", jsonArray (fmap jsonString exampleResult)) +        ] + +jsonDoc (DocHeader header) = jsonObject +    [ ("tag", jsonString "DocHeader") +    , ("header", jsonHeader header) +    ] +  where +    jsonHeader Header{..} = jsonObject +        [ ("headerLevel", jsonInt headerLevel) +        , ("headerTitle", jsonDoc headerTitle) +        ] + +jsonDoc (DocTable table) = jsonObject +    [ ("tag", jsonString "DocTable") +    , ("table", jsonTable table) +    ] +  where +    jsonTable Table{..} = jsonObject +        [ ("tableHeaderRows", jsonArray (fmap jsonTableRow tableHeaderRows)) +        , ("tableBodyRows", jsonArray (fmap jsonTableRow tableBodyRows)) +        ] + +    jsonTableRow TableRow{..} = jsonArray (fmap jsonTableCell tableRowCells) + +    jsonTableCell TableCell{..} = jsonObject +        [ ("tableCellColspan", jsonInt tableCellColspan) +        , ("tableCellRowspan", jsonInt tableCellRowspan) +        , ("tableCellContents", jsonDoc tableCellContents) +        ] +  jsonModule :: Module -> JsonDoc  jsonModule = JSString . moduleStableString diff --git a/haddock-api/src/Haddock/Interface/LexParseRn.hs b/haddock-api/src/Haddock/Interface/LexParseRn.hs index 87064a0f..2df2bbbf 100644 --- a/haddock-api/src/Haddock/Interface/LexParseRn.hs +++ b/haddock-api/src/Haddock/Interface/LexParseRn.hs @@ -20,9 +20,9 @@ module Haddock.Interface.LexParseRn    , processModuleHeader    ) where -import GHC.Types.Avail  import Control.Arrow  import Control.Monad +import Data.Functor  import Data.List ((\\), maximumBy)  import Data.Ord  import Documentation.Haddock.Doc (metaDocConcat) @@ -33,10 +33,11 @@ import Haddock.Interface.ParseModuleHeader  import Haddock.Parser  import Haddock.Types  import GHC.Types.Name +import GHC.Types.Avail ( availName ) +import GHC.Parser.PostProcess  import GHC.Driver.Ppr ( showPpr, showSDoc )  import GHC.Types.Name.Reader  import GHC.Data.EnumSet as EnumSet -import GHC.Rename.Env (dataTcOccs)  processDocStrings :: DynFlags -> Maybe Package -> GlobalRdrEnv -> [HsDocString]                    -> ErrMsgM (Maybe (MDoc Name)) @@ -90,24 +91,38 @@ processModuleHeader dflags pkgName gre safety mayStr = do  -- fallbacks in case we can't locate the identifiers.  --  -- See the comments in the source for implementation commentary. -rename :: DynFlags -> GlobalRdrEnv -> Doc RdrName -> ErrMsgM (Doc Name) +rename :: DynFlags -> GlobalRdrEnv -> Doc NsRdrName -> ErrMsgM (Doc Name)  rename dflags gre = rn    where      rn d = case d of        DocAppend a b -> DocAppend <$> rn a <*> rn b        DocParagraph doc -> DocParagraph <$> rn doc -      DocIdentifier x -> do +      DocIdentifier i -> do +        let NsRdrName ns x = unwrap i +            occ = rdrNameOcc x +            isValueName = isDataOcc occ || isVarOcc occ + +        let valueNsChoices | isValueName = [x] +                           | otherwise   = [] -- is this ever possible? +            typeNsChoices  | isValueName = [setRdrNameSpace x tcName] +                           | otherwise   = [x] +          -- Generate the choices for the possible kind of thing this -        -- is. -        let choices = dataTcOccs x +        -- is. We narrow down the possibilities with the namespace (if +        -- there is one). +        let choices = case ns of +                        Value -> valueNsChoices +                        Type  -> typeNsChoices +                        None  -> valueNsChoices ++ typeNsChoices          -- Lookup any GlobalRdrElts that match the choices.          case concatMap (\c -> lookupGRE_RdrName c gre) choices of            -- 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))) +              -- The only way this can happen is if a value namespace was +              -- specified on something that cannot be a value. +              [] -> invalidValue dflags i                -- There was nothing in the environment so we need to                -- pick some default from what's available to us. We @@ -117,14 +132,14 @@ 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:_ -> outOfScope dflags a +              a:_ -> outOfScope dflags ns (i $> a)            -- There is only one name in the environment that matches so            -- use it. -          [a] -> pure (DocIdentifier (greMangledName a)) +          [a] -> pure $ DocIdentifier (i $> greMangledName a)            -- There are multiple names available. -          gres -> ambiguous dflags x gres +          gres -> ambiguous dflags i gres        DocWarning doc -> DocWarning <$> rn doc        DocEmphasis doc -> DocEmphasis <$> rn doc @@ -156,19 +171,25 @@ 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 -> ErrMsgM (Doc a) -outOfScope dflags x = -  case x of -    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 +outOfScope :: DynFlags -> Namespace -> Wrap RdrName -> ErrMsgM (Doc a) +outOfScope dflags ns x = +  case unwrap x of +    Unqual occ -> warnAndMonospace (x $> occ) +    Qual mdl occ -> pure (DocIdentifierUnchecked (x $> (mdl, occ))) +    Orig _ occ -> warnAndMonospace (x $> occ) +    Exact name -> warnAndMonospace (x $> name)  -- Shouldn't happen since x is out of scope    where +    prefix = case ns of +               Value -> "the value " +               Type -> "the type " +               None -> "" +      warnAndMonospace a = do -      tell ["Warning: '" ++ showPpr dflags a ++ "' is out of scope.\n" ++ +      let a' = showWrapped (showPpr dflags) a +      tell ["Warning: " ++ prefix ++ "'" ++ a' ++ "' is out of scope.\n" ++              "    If you qualify the identifier, haddock can try to link it anyway."] -      pure (monospaced a) -    monospaced a = DocMonospaced (DocString (showPpr dflags a)) +      pure (monospaced a') +    monospaced = DocMonospaced . DocString  -- | Handle ambiguous identifiers.  -- @@ -176,26 +197,42 @@ outOfScope dflags x =  --  -- Emits a warning if the 'GlobalRdrElts's don't belong to the same type or class.  ambiguous :: DynFlags -          -> RdrName +          -> Wrap NsRdrName            -> [GlobalRdrElt] -- ^ More than one @gre@s sharing the same `RdrName` above.            -> ErrMsgM (Doc Name)  ambiguous dflags x gres = do    let noChildren = map availName (gresToAvailInfo gres)        dflt = maximumBy (comparing (isLocalName &&& isTyConName)) noChildren -      msg = "Warning: " ++ x_str ++ " is ambiguous. It is defined\n" ++ +      msg = "Warning: " ++ showNsRdrName dflags x ++ " is ambiguous. It is defined\n" ++              concatMap (\n -> "    * " ++ defnLoc n ++ "\n") (map greMangledName gres) ++              "    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 +            "    by specifying the type/value namespace explicitly.\n" ++ +            "    Defaulting to the one defined " ++ defnLoc dflt    -- TODO: Once we have a syntax for namespace qualification (#667) we may also    -- want to emit a warning when an identifier is a data constructor for a type    -- of the same name, but not the only constructor.    -- For example, for @data D = C | D@, someone may want to reference the @D@    -- constructor.    when (length noChildren > 1) $ tell [msg] -  pure (DocIdentifier dflt) +  pure (DocIdentifier (x $> dflt))    where      isLocalName (nameSrcLoc -> RealSrcLoc {}) = True      isLocalName _ = False -    x_str = '\'' : showPpr dflags x ++ "'"      defnLoc = showSDoc dflags . pprNameDefnLoc + +-- | Handle value-namespaced names that cannot be for values. +-- +-- Emits a warning that the value-namespace is invalid on a non-value identifier. +invalidValue :: DynFlags -> Wrap NsRdrName -> ErrMsgM (Doc a) +invalidValue dflags x = do +  tell ["Warning: " ++ showNsRdrName dflags x ++ " cannot be value, yet it is\n" ++ +            "    namespaced as such. Did you mean to specify a type namespace\n" ++ +            "    instead?"] +  pure (DocMonospaced (DocString (showNsRdrName dflags x))) + +-- | Printable representation of a wrapped and namespaced name +showNsRdrName :: DynFlags -> Wrap NsRdrName -> String +showNsRdrName dflags = (\p i -> p ++ "'" ++ i ++ "'") <$> prefix <*> ident +  where +    ident = showWrapped (showPpr dflags . rdrName) +    prefix = renderNs . namespace . unwrap diff --git a/haddock-api/src/Haddock/Interface/ParseModuleHeader.hs b/haddock-api/src/Haddock/Interface/ParseModuleHeader.hs index 611d8b6f..3e464fbc 100644 --- a/haddock-api/src/Haddock/Interface/ParseModuleHeader.hs +++ b/haddock-api/src/Haddock/Interface/ParseModuleHeader.hs @@ -1,4 +1,6 @@  {-# OPTIONS_GHC -Wwarn #-} +{-# LANGUAGE DeriveFunctor #-} +  -----------------------------------------------------------------------------  -- |  -- Module      :  Haddock.Interface.ParseModuleHeader @@ -11,12 +13,12 @@  -----------------------------------------------------------------------------  module Haddock.Interface.ParseModuleHeader (parseModuleHeader) where -import Control.Monad (mplus) +import Control.Applicative (Alternative (..)) +import Control.Monad (ap)  import Data.Char  import GHC.Driver.Session  import Haddock.Parser  import Haddock.Types -import GHC.Types.Name.Reader  -- -----------------------------------------------------------------------------  -- Parsing module headers @@ -24,37 +26,47 @@ import GHC.Types.Name.Reader  -- 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 -> Maybe Package -> String -> (HaddockModInfo RdrName, MDoc RdrName) +parseModuleHeader :: DynFlags -> Maybe Package -> String -> (HaddockModInfo NsRdrName, MDoc NsRdrName)  parseModuleHeader dflags pkgName str0 =     let -      getKey :: String -> String -> (Maybe String,String) -      getKey key str = case parseKey key str of -         Nothing -> (Nothing,str) -         Just (value,rest) -> (Just value,rest) - -      (_moduleOpt,str1) = getKey "Module" str0 -      (descriptionOpt,str2) = getKey "Description" str1 -      (copyrightOpt,str3) = getKey "Copyright" str2 -      (licenseOpt,str4) = getKey "License" str3 -      (licenceOpt,str5) = getKey "Licence" str4 -      (spdxLicenceOpt,str6) = getKey "SPDX-License-Identifier" str5 -      (maintainerOpt,str7) = getKey "Maintainer" str6 -      (stabilityOpt,str8) = getKey "Stability" str7 -      (portabilityOpt,str9) = getKey "Portability" str8 +      kvs :: [(String, String)] +      str1 :: String + +      (kvs, str1) = maybe ([], str0) id $ runP fields str0 + +      -- trim whitespaces +      trim :: String -> String +      trim = dropWhile isSpace . reverse . dropWhile isSpace . reverse + +      getKey :: String -> Maybe String +      getKey key = fmap trim (lookup key kvs) + +      descriptionOpt = getKey "Description" +      copyrightOpt   = getKey "Copyright" +      licenseOpt     = getKey "License" +      licenceOpt     = getKey "Licence" +      spdxLicenceOpt = getKey "SPDX-License-Identifier" +      maintainerOpt  = getKey "Maintainer" +      stabilityOpt   = getKey "Stability" +      portabilityOpt = getKey "Portability"     in (HaddockModInfo {            hmi_description = parseString dflags <$> descriptionOpt,            hmi_copyright = copyrightOpt, -          hmi_license = spdxLicenceOpt `mplus` licenseOpt `mplus` licenceOpt, +          hmi_license = spdxLicenceOpt <|> licenseOpt <|> 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 pkgName str9) +          }, parseParas dflags pkgName str1) + +------------------------------------------------------------------------------- +-- Small parser to parse module header. +------------------------------------------------------------------------------- --- | This function is how we read keys. +-- | The below is a small parser framework how we read keys.  --  -- all fields in the header are optional and have the form  -- @@ -73,78 +85,105 @@ parseModuleHeader dflags pkgName str0 =  --  -- the value will be "this is a .. description" and the rest will begin  -- at "The module comment". -parseKey :: String -> String -> Maybe (String,String) -parseKey key toParse0 = -   do -      let -         (spaces0,toParse1) = extractLeadingSpaces (dropWhile (`elem` ['\r', '\n']) toParse0) - -         indentation = spaces0 -      afterKey0 <- extractPrefix key toParse1 -      let -         afterKey1 = extractLeadingSpaces afterKey0 -      afterColon0 <- case snd afterKey1 of -         ':':afterColon -> return afterColon -         _ -> Nothing -      let -         (_,afterColon1) = extractLeadingSpaces afterColon0 - -      return (scanKey True indentation afterColon1) -   where -      scanKey :: Bool -> String -> String -> (String,String) -      scanKey _       _           [] = ([],[]) -      scanKey isFirst indentation str = -         let -            (nextLine,rest1) = extractNextLine str - -            accept = isFirst || sufficientIndentation || allSpaces - -            sufficientIndentation = case extractPrefix indentation nextLine of -               Just (c:_) | isSpace c -> True -               _ -> False - -            allSpaces = case extractLeadingSpaces nextLine of -               (_,[]) -> True -               _ -> False -         in -            if accept -               then -                  let -                     (scanned1,rest2) = scanKey False indentation rest1 - -                     scanned2 = case scanned1 of -                        "" -> if allSpaces then "" else nextLine -                        _ -> nextLine ++ "\n" ++ scanned1 -                  in -                     (scanned2,rest2) -               else -                  ([],str) - -      extractLeadingSpaces :: String -> (String,String) -      extractLeadingSpaces [] = ([],[]) -      extractLeadingSpaces (s@(c:cs)) -         | isSpace c = -            let -               (spaces1,cs1) = extractLeadingSpaces cs -            in -               (c:spaces1,cs1) -         | otherwise = ([],s) - -      extractNextLine :: String -> (String,String) -      extractNextLine [] = ([],[]) -      extractNextLine (c:cs) -         | c == '\n' = -            ([],cs) -         | otherwise = -            let -               (line,rest) = extractNextLine cs -            in -               (c:line,rest) - -      -- comparison is case-insensitive. -      extractPrefix :: String -> String -> Maybe String -      extractPrefix [] s = Just s -      extractPrefix _ [] = Nothing -      extractPrefix (c1:cs1) (c2:cs2) -         | toUpper c1 == toUpper c2 = extractPrefix cs1 cs2 -         | otherwise = Nothing + +-- | 'C' is a 'Char' carrying its column. +-- +-- This let us make an indentation-aware parser, as we know current indentation. +-- by looking at the next character in the stream ('curInd'). +-- +-- Thus we can munch all spaces but only not-spaces which are indented. +-- +data C = C {-# UNPACK #-} !Int Char + +newtype P a = P { unP :: [C] -> Maybe ([C], a) } +  deriving Functor + +instance Applicative P where +    pure x = P $ \s -> Just (s, x) +    (<*>)  = ap + +instance Monad P where +    return = pure +    m >>= k = P $ \s0 -> do +        (s1, x) <- unP m s0 +        unP (k x) s1 + +instance Alternative P where +    empty   = P $ \_ -> Nothing +    a <|> b = P $ \s -> unP a s <|> unP b s + +runP :: P a -> String -> Maybe a +runP p input = fmap snd (unP p input') +  where +    input' = concat +        [ zipWith C [0..] l ++ [C (length l) '\n'] +        | l <- lines input +        ] + +------------------------------------------------------------------------------- +-- +------------------------------------------------------------------------------- + +curInd :: P Int +curInd = P $ \s -> Just . (,) s $ case s of +    []        -> 0 +    C i _ : _ -> i + +rest :: P String +rest = P $ \cs -> Just ([], [ c | C _ c <- cs ]) + +munch :: (Int -> Char -> Bool) -> P String +munch p = P $ \cs -> +    let (xs,ys) = takeWhileMaybe p' cs in Just (ys, xs) +  where +    p' (C i c) +        | p i c  = Just c +        | otherwise = Nothing + +munch1 :: (Int -> Char -> Bool) -> P String +munch1 p = P $ \s -> case s of +    [] -> Nothing +    (c:cs) | Just c' <- p' c -> let (xs,ys) = takeWhileMaybe p' cs in Just (ys, c' : xs) +           | otherwise -> Nothing +  where +    p' (C i c) +        | p i c  = Just c +        | otherwise = Nothing + +char :: Char -> P Char +char c = P $ \s -> case s of +    []                        -> Nothing +    (C _ c' : cs) | c == c'   -> Just (cs, c) +                  | otherwise -> Nothing + +skipSpaces :: P () +skipSpaces = P $ \cs -> Just (dropWhile (\(C _ c) -> isSpace c) cs, ()) + +takeWhileMaybe :: (a -> Maybe b) -> [a] -> ([b], [a]) +takeWhileMaybe f = go where +    go xs0@[] = ([], xs0) +    go xs0@(x:xs) = case f x of +        Just y  -> let (ys, zs) = go xs in (y : ys, zs) +        Nothing -> ([], xs0) + +------------------------------------------------------------------------------- +-- Fields +------------------------------------------------------------------------------- + +field :: Int -> P (String, String) +field i = do +    fn <- munch1 $ \_ c -> isAlpha c || c == '-' +    skipSpaces +    _ <- char ':' +    skipSpaces +    val <- munch $ \j c -> isSpace c || j > i +    return (fn, val) + +fields :: P ([(String, String)], String) +fields = do +    skipSpaces +    i  <- curInd +    fs <- many (field i) +    r  <- rest +    return (fs, r) + diff --git a/haddock-api/src/Haddock/Interface/Rename.hs b/haddock-api/src/Haddock/Interface/Rename.hs index 14032d15..b212adce 100644 --- a/haddock-api/src/Haddock/Interface/Rename.hs +++ b/haddock-api/src/Haddock/Interface/Rename.hs @@ -29,12 +29,22 @@ import GHC.Builtin.Types (eqTyCon_RDR)  import Control.Applicative  import Control.Arrow ( first )  import Control.Monad hiding (mapM) +import Data.List (intercalate)  import qualified Data.Map as Map hiding ( Map ) +import qualified Data.Set as Set  import Prelude hiding (mapM)  import GHC.HsToCore.Docs -renameInterface :: DynFlags -> LinkEnv -> Bool -> Interface -> ErrMsgM Interface -renameInterface dflags renamingEnv warnings iface = +-- | Traverse docstrings and ASTs in the Haddock interface, renaming 'Name' to +-- 'DocName'. +-- +-- What this really boils down to is: for each 'Name', figure out which of the +-- modules that export the name is the preferred place to link to. +-- +-- The renamed output gets written into fields in the Haddock interface record +-- that were previously left empty. +renameInterface :: DynFlags -> [String] -> LinkEnv -> Bool -> Interface -> ErrMsgM Interface +renameInterface _dflags ignoredSymbols renamingEnv warnings iface =    -- first create the local env, where every name exported by this module    -- is mapped to itself, and everything else comes from the global renaming @@ -69,8 +79,15 @@ renameInterface dflags renamingEnv warnings iface =        -- 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 + +      qualifiedName n = (moduleNameString $ moduleName $ nameModule n) <> "." <> getOccString n + +      ignoreSet = Set.fromList ignoredSymbols + +      strings = [ qualifiedName n +                  | n <- missingNames +                , not (qualifiedName n `Set.member` ignoreSet)                  , not (isSystemName n)                  , not (isBuiltInSyntax n)                  , Exact n /= eqTyCon_RDR @@ -82,7 +99,7 @@ renameInterface dflags renamingEnv warnings iface =      unless (OptHide `elem` ifaceOptions iface || null strings || not warnings) $        tell ["Warning: " ++ moduleString (ifaceMod iface) ++              ": could not find link destinations for:\n"++ -            unwords ("   " : strings) ] +            intercalate "\n\t- "  ("" : strings) ]      return $ iface { ifaceRnDoc         = finalModuleDoc,                       ifaceRnDocMap      = rnDocMap, @@ -130,6 +147,11 @@ lookupRn name = RnM $ \lkp ->      (False,maps_to) -> (maps_to, (name :))      (True, maps_to) -> (maps_to, id) +-- | Look up a 'Name' in the renaming environment, but don't warn if you don't +-- find the name. Prefer to use 'lookupRn' whenever possible. +lookupRnNoWarn :: Name -> RnM DocName +lookupRnNoWarn name = RnM $ \lkp -> (snd (lkp name), id) +  -- | Run the renamer action using lookup in a 'LinkEnv' as the lookup function.  -- Returns the renamed value along with a list of `Name`'s that could not be  -- renamed because they weren't in the environment. @@ -173,8 +195,8 @@ renameLDocHsSyn :: LHsDocString -> RnM LHsDocString  renameLDocHsSyn = return -renameDoc :: Traversable t => t Name -> RnM (t DocName) -renameDoc = traverse rename +renameDoc :: Traversable t => t (Wrap Name) -> RnM (t (Wrap DocName)) +renameDoc = traverse (traverse rename)  renameFnArgsDoc :: FnArgsDoc Name -> RnM (FnArgsDoc DocName)  renameFnArgsDoc = mapM renameDoc @@ -559,7 +581,7 @@ renameSig sig = case sig of      lnames' <- mapM renameL lnames      return $ FixSig noExtField (FixitySig noExtField lnames' fixity)    MinimalSig _ src (L l s) -> do -    s' <- traverse renameL s +    s' <- traverse (traverse lookupRnNoWarn) s      return $ MinimalSig noExtField src (L l s')    -- we have filtered out all other kinds of signatures in Interface.Create    _ -> error "expected TypeSig" diff --git a/haddock-api/src/Haddock/Interface/Specialize.hs b/haddock-api/src/Haddock/Interface/Specialize.hs index 85055bf4..c6d61d05 100644 --- a/haddock-api/src/Haddock/Interface/Specialize.hs +++ b/haddock-api/src/Haddock/Interface/Specialize.hs @@ -11,6 +11,7 @@ module Haddock.Interface.Specialize      ) where +import Haddock.GhcUtils ( hsTyVarBndrName )  import Haddock.Syb  import Haddock.Types @@ -58,13 +59,9 @@ specialize specs = go spec_map0  -- Again, it is just a convenience function around 'specialize'. Note that  -- length of type list should be the same as the number of binders.  specializeTyVarBndrs :: Data a => LHsQTyVars GhcRn -> [HsType GhcRn] -> a -> a -specializeTyVarBndrs bndrs typs = -    specialize $ zip bndrs' typs +specializeTyVarBndrs bndrs typs = specialize $ zip bndrs' typs    where -    bndrs' = map (bname . unLoc) . hsq_explicit $ bndrs -    bname (UserTyVar _ _ (L _ name)) = name -    bname (KindedTyVar _ _ (L _ name) _) = name -    bname (XTyVarBndr _) = error "haddock:specializeTyVarBndrs" +    bndrs' = map (hsTyVarBndrName . unLoc) . hsq_explicit $ bndrs diff --git a/haddock-api/src/Haddock/InterfaceFile.hs b/haddock-api/src/Haddock/InterfaceFile.hs index 4455f0f8..9c34da54 100644 --- a/haddock-api/src/Haddock/InterfaceFile.hs +++ b/haddock-api/src/Haddock/InterfaceFile.hs @@ -22,9 +22,9 @@ module Haddock.InterfaceFile (  import Haddock.Types -import Haddock.Utils hiding (out)  import Control.Monad +import Control.Monad.IO.Class ( MonadIO(..) )  import Data.Array  import Data.IORef  import Data.List (mapAccumR) @@ -84,7 +84,7 @@ binaryInterfaceMagic = 0xD0Cface  --  binaryInterfaceVersion :: Word16  #if MIN_VERSION_ghc(9,1,0) && !MIN_VERSION_ghc(9,2,0) -binaryInterfaceVersion = 34 +binaryInterfaceVersion = 38  binaryInterfaceVersionCompatibility :: [Word16]  binaryInterfaceVersionCompatibility = [binaryInterfaceVersion] @@ -702,3 +702,28 @@ instance Binary DocName where          name <- get bh          return (Undocumented name)        _ -> error "get DocName: Bad h" + +instance Binary n => Binary (Wrap n) where +  put_ bh (Unadorned n) = do +    putByte bh 0 +    put_ bh n +  put_ bh (Parenthesized n) = do +    putByte bh 1 +    put_ bh n +  put_ bh (Backticked n) = do +    putByte bh 2 +    put_ bh n + +  get bh = do +    h <- getByte bh +    case h of +      0 -> do +        name <- get bh +        return (Unadorned name) +      1 -> do +        name <- get bh +        return (Parenthesized name) +      2 -> do +        name <- get bh +        return (Backticked name) +      _ -> error "get Wrap: Bad h" diff --git a/haddock-api/src/Haddock/Options.hs b/haddock-api/src/Haddock/Options.hs index 04189b99..4d22505f 100644 --- a/haddock-api/src/Haddock/Options.hs +++ b/haddock-api/src/Haddock/Options.hs @@ -37,14 +37,14 @@ module Haddock.Options (    readIfaceArgs,    optPackageName,    optPackageVersion, -  modulePackageInfo +  modulePackageInfo, +  ignoredSymbols  ) where  import qualified Data.Char as Char  import           Data.Version  import           Control.Applicative -import           Distribution.Verbosity  import           GHC.Data.FastString  import           GHC ( Module, moduleUnit )  import           GHC.Unit.State @@ -110,6 +110,7 @@ data Flag    | Flag_PackageVersion String    | Flag_Reexport String    | Flag_SinceQualification String +  | Flag_IgnoreLinkSymbol String    | Flag_ParCount (Maybe Int)    deriving (Eq, Show) @@ -223,6 +224,8 @@ options backwardsCompat =        "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'", +    Option [] ["ignore-link-symbol"] (ReqArg Flag_IgnoreLinkSymbol "SYMBOL") +      "name of a symbol which does not trigger a warning in case of link issue",      Option ['j'] [] (OptArg (\count -> Flag_ParCount (fmap read count)) "n")        "load modules in parallel"    ] @@ -337,11 +340,13 @@ sinceQualification flags =  verbosity :: [Flag] -> Verbosity  verbosity flags =    case [ str | Flag_Verbosity str <- flags ] of -    []  -> normal +    []  -> Normal      x:_ -> case parseVerbosity x of        Left e -> throwE e        Right v -> v +ignoredSymbols :: [Flag] -> [String] +ignoredSymbols flags = [ symbol | Flag_IgnoreLinkSymbol symbol <- flags ]  ghcFlags :: [Flag] -> [String]  ghcFlags flags = [ option | Flag_OptGhc option <- flags ] diff --git a/haddock-api/src/Haddock/Parser.hs b/haddock-api/src/Haddock/Parser.hs index 366bcd55..ab2fa549 100644 --- a/haddock-api/src/Haddock/Parser.hs +++ b/haddock-api/src/Haddock/Parser.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE ViewPatterns #-}  -- |  -- Module      :  Haddock.Parser  -- Copyright   :  (c) Mateusz Kowalczyk 2013, @@ -15,27 +16,42 @@ module Haddock.Parser ( parseParas  import qualified Documentation.Haddock.Parser as P  import Documentation.Haddock.Types +import Haddock.Types  import GHC.Driver.Session ( DynFlags )  import GHC.Driver.Config  import GHC.Data.FastString   ( fsLit ) -import GHC.Parser.Lexer ( initParserState, unP, ParseResult(POk) ) +import GHC.Parser.Lexer ( initParserState, unP, ParseResult(POk, PFailed) )  import GHC.Parser       ( parseIdentifier ) -import GHC.Types.Name.Reader ( RdrName ) -import GHC.Types.SrcLoc ( mkRealSrcLoc, unLoc ) +import GHC.Types.Name.Occurrence ( occNameString ) +import GHC.Types.Name.Reader ( RdrName(..) ) +import GHC.Types.SrcLoc ( mkRealSrcLoc, GenLocated(..) )  import GHC.Data.StringBuffer ( stringToStringBuffer ) -parseParas :: DynFlags -> Maybe Package -> String -> MetaDoc mod RdrName + +parseParas :: DynFlags -> Maybe Package -> String -> MetaDoc mod (Wrap NsRdrName)  parseParas d p = overDoc (P.overIdentifier (parseIdent d)) . P.parseParas p -parseString :: DynFlags -> String -> DocH mod RdrName +parseString :: DynFlags -> String -> DocH mod (Wrap NsRdrName)  parseString d = P.overIdentifier (parseIdent d) . P.parseString -parseIdent :: DynFlags -> String -> Maybe RdrName -parseIdent dflags str0 = -  let buffer = stringToStringBuffer str0 -      realSrcLc = mkRealSrcLoc (fsLit "<unknown file>") 0 0 -      pstate = initParserState (initParserOpts dflags) buffer realSrcLc -  in case unP parseIdentifier pstate of -    POk _ name -> Just (unLoc name) -    _ -> Nothing +parseIdent :: DynFlags -> Namespace -> String -> Maybe (Wrap NsRdrName) +parseIdent dflags ns str0 = +  case unP parseIdentifier (pstate str1) of +    POk _ (L _ name) +      -- Guards against things like 'Q.--', 'Q.case', etc. +      -- See https://github.com/haskell/haddock/issues/952 and Trac #14109 +      | Qual _ occ <- name +      , PFailed{} <- unP parseIdentifier (pstate (occNameString occ)) +      -> Nothing +      | otherwise +      -> Just (wrap (NsRdrName ns name)) +    PFailed{} -> Nothing +  where +    realSrcLc = mkRealSrcLoc (fsLit "<unknown file>") 0 0 +    pstate str = initParserState (initParserOpts dflags) (stringToStringBuffer str) realSrcLc +    (wrap,str1) = case str0 of +                    '(' : s@(c : _) | c /= ',', c /= ')'  -- rule out tuple names +                                    -> (Parenthesized, init s) +                    '`' : s@(_ : _) -> (Backticked,    init s) +                    _               -> (Unadorned,     str0) diff --git a/haddock-api/src/Haddock/Types.hs b/haddock-api/src/Haddock/Types.hs index 74a17fbb..7fd11d69 100644 --- a/haddock-api/src/Haddock/Types.hs +++ b/haddock-api/src/Haddock/Types.hs @@ -34,13 +34,15 @@ module Haddock.Types (    , tell   ) where -import Control.Exception  import Control.DeepSeq +import Control.Exception (throw) +import Control.Monad.Catch  import Control.Monad.IO.Class (MonadIO(..))  import Control.Monad.Writer.Strict (Writer, WriterT, MonadWriter(..), lift, runWriter, runWriterT)  import Data.Typeable (Typeable)  import Data.Map (Map)  import Data.Data (Data) +import Data.Void (Void)  import Documentation.Haddock.Types  import GHC.Types.Basic (PromotionFlag(..))  import GHC.Types.Fixity (Fixity(..)) @@ -291,6 +293,12 @@ noDocForDecl = (Documentation Nothing Nothing, mempty)  -- | Type of environment used to cross-reference identifiers in the syntax.  type LinkEnv = Map Name Module +-- | An 'RdrName' tagged with some type/value namespace information. +data NsRdrName = NsRdrName +  { namespace :: !Namespace +  , rdrName :: !RdrName +  } +  -- | Extends 'Name' with cross-reference information.  data DocName    = Documented Name Module @@ -339,7 +347,30 @@ instance SetName DocName where      setName name' (Documented _ mdl) = Documented name' mdl      setName name' (Undocumented _) = Undocumented name' +-- | Adds extra "wrapper" information to a name. +-- +-- This is to work around the fact that most name types in GHC ('Name', 'RdrName', +-- 'OccName', ...) don't include backticks or parens. +data Wrap n +  = Unadorned { unwrap :: n  }     -- ^ don't do anything to the name +  | Parenthesized { unwrap :: n }  -- ^ add parentheses around the name +  | Backticked { unwrap :: n }     -- ^ add backticks around the name +  deriving (Show, Functor, Foldable, Traversable) + +-- | Useful for debugging +instance Outputable n => Outputable (Wrap n) where +  ppr (Unadorned n)     = ppr n +  ppr (Parenthesized n) = hcat [ char '(', ppr n, char ')' ] +  ppr (Backticked n)    = hcat [ char '`', ppr n, char '`' ] + +showWrapped :: (a -> String) -> Wrap a -> String +showWrapped f (Unadorned n) = f n +showWrapped f (Parenthesized n) = "(" ++ f n ++ ")" +showWrapped f (Backticked n) = "`" ++ f n ++ "`" +instance HasOccName DocName where + +    occName = occName . getName  -----------------------------------------------------------------------------  -- * Instances @@ -433,10 +464,10 @@ instance NamedThing name => NamedThing (InstOrigin name) where  type LDoc id = Located (Doc id) -type Doc id = DocH (ModuleName, OccName) id -type MDoc id = MetaDoc (ModuleName, OccName) id +type Doc id = DocH (Wrap (ModuleName, OccName)) (Wrap id) +type MDoc id = MetaDoc (Wrap (ModuleName, OccName)) (Wrap id) -type DocMarkup id a = DocMarkupH (ModuleName, OccName) id a +type DocMarkup id a = DocMarkupH (Wrap (ModuleName, OccName)) id a  instance (NFData a, NFData mod)           => NFData (DocH mod a) where @@ -610,17 +641,28 @@ type ErrMsgM = Writer [ErrMsg]  -- | Haddock's own exception type. -data HaddockException = HaddockException String deriving Typeable +data HaddockException +  = HaddockException String +  | WithContext [String] SomeException +  deriving Typeable  instance Show HaddockException where    show (HaddockException str) = str - +  show (WithContext ctxts se)  = unlines $ ["While " ++ ctxt ++ ":\n" | ctxt <- reverse ctxts] ++ [show se]  throwE :: String -> a  instance Exception HaddockException  throwE str = throw (HaddockException str) +withExceptionContext :: MonadCatch m => String -> m a -> m a +withExceptionContext ctxt = +  handle (\ex -> +      case ex of +        HaddockException _ -> throwM $ WithContext [ctxt] (toException ex) +        WithContext ctxts se -> throwM $ WithContext (ctxt:ctxts) se +          ) . +  handle (throwM . WithContext [ctxt])  -- In "Haddock.Interface.Create", we need to gather  -- @Haddock.Types.ErrMsg@s a lot, like @ErrMsgM@ does, @@ -671,7 +713,7 @@ type instance XOpTy            DocNameI = NoExtField  type instance XParTy           DocNameI = NoExtField  type instance XIParamTy        DocNameI = NoExtField  type instance XKindSig         DocNameI = NoExtField -type instance XSpliceTy        DocNameI = NoExtField +type instance XSpliceTy        DocNameI = Void       -- see `renameHsSpliceTy`  type instance XDocTy           DocNameI = NoExtField  type instance XBangTy          DocNameI = NoExtField  type instance XRecTy           DocNameI = NoExtField diff --git a/haddock-api/src/Haddock/Utils.hs b/haddock-api/src/Haddock/Utils.hs index 8a6b6349..314b8db9 100644 --- a/haddock-api/src/Haddock/Utils.hs +++ b/haddock-api/src/Haddock/Utils.hs @@ -16,16 +16,9 @@  -----------------------------------------------------------------------------  module Haddock.Utils ( -  -- * Misc utilities -  restrictTo, emptyHsQTvs, -  toDescription, toInstalledDescription, -  mkEmptySigWcType, mkEmptySigType, -  addClassContext, lHsQTyVarsToTypes, -    -- * Filename utilities    moduleHtmlFile, moduleHtmlFile',    contentsHtmlFile, indexHtmlFile, indexJsonFile, -  moduleIndexFrameName, mainFrameName, synopsisFrameName,    subIndexHtmlFile,    haddockJsFile, jsQuickJumpFile,    quickJumpCssFile, @@ -36,7 +29,7 @@ module Haddock.Utils (    makeAnchorId,    -- * Miscellaneous utilities -  getProgramName, bye, die, dieMsg, noDieMsg, mapSnd, mapMaybeM, escapeStr, +  getProgramName, bye, die, escapeStr,    writeUtf8File, withTempDir,    -- * HTML cross reference mapping @@ -49,11 +42,8 @@ module Haddock.Utils (    replace,    spanWith, -  -- * MTL stuff -  MonadIO(..), -    -- * Logging -  parseVerbosity, +  parseVerbosity, Verbosity(..), silent, normal, verbose, deafening,    out,    -- * System tools @@ -63,46 +53,54 @@ module Haddock.Utils (  import Documentation.Haddock.Doc (emptyMetaDoc)  import Haddock.Types -import Haddock.GhcUtils -import GHC.Types.Basic ( PromotionFlag(..) ) -import GHC.Utils.Exception (ExceptionMonad)  import GHC  import GHC.Types.Name -import Control.Monad ( liftM ) -import Control.Monad.Catch ( bracket_ ) +import Control.Monad.IO.Class ( MonadIO(..) ) +import Control.Monad.Catch ( MonadMask, bracket_ )  import Data.Char ( isAlpha, isAlphaNum, isAscii, ord, chr )  import Numeric ( showIntAtBase )  import Data.Map ( Map )  import qualified Data.Map as Map hiding ( Map )  import Data.IORef ( IORef, newIORef, readIORef )  import Data.List ( isSuffixOf ) -import Data.Maybe ( mapMaybe )  import System.Environment ( getProgName )  import System.Exit  import System.Directory ( createDirectory, removeDirectoryRecursive ) -import System.IO ( hPutStr, hSetEncoding, IOMode(..), stderr, utf8, withFile ) +import System.IO ( hPutStr, hSetEncoding, IOMode(..), utf8, withFile )  import System.IO.Unsafe ( unsafePerformIO )  import qualified System.FilePath.Posix as HtmlPath -import Distribution.Verbosity -import Distribution.ReadE  #ifndef mingw32_HOST_OS  import qualified System.Posix.Internals  #endif -import GHC.Utils.Monad ( MonadIO(..) ) - -  --------------------------------------------------------------------------------  -- * Logging  -------------------------------------------------------------------------------- +data Verbosity = Silent | Normal | Verbose | Deafening +  deriving (Eq, Ord, Enum, Bounded, Show) -parseVerbosity :: String -> Either String Verbosity -parseVerbosity = runReadE flagToVerbosity +silent, normal, verbose, deafening :: Verbosity +silent    = Silent +normal    = Normal +verbose   = Verbose +deafening = Deafening +-- | Parse out a verbosity level. Inspired from Cabal's verbosity parsing. +parseVerbosity :: String -> Either String Verbosity +parseVerbosity "0" = Right Silent +parseVerbosity "1" = Right Normal +parseVerbosity "2" = Right Silent +parseVerbosity "3" = Right Deafening +parseVerbosity "silent"    = return Silent +parseVerbosity "normal"    = return Normal +parseVerbosity "verbose"   = return Verbose +parseVerbosity "debug"     = return Deafening +parseVerbosity "deafening" = return Deafening +parseVerbosity other = Left ("Can't parse verbosity " ++ other)  -- | Print a message to stdout, if it is not too verbose  out :: MonadIO m @@ -119,144 +117,14 @@ out progVerbosity msgVerbosity msg  -------------------------------------------------------------------------------- --- | Extract a module's short description. -toDescription :: Interface -> Maybe (MDoc Name) -toDescription = fmap mkMeta . hmi_description . ifaceInfo - - --- | Extract a module's short description. -toInstalledDescription :: InstalledInterface -> Maybe (MDoc Name) -toInstalledDescription = fmap mkMeta . hmi_description . instInfo  mkMeta :: Doc a -> MDoc a  mkMeta x = emptyMetaDoc { _doc = x } -mkEmptySigWcType :: LHsType GhcRn -> LHsSigWcType GhcRn --- Dubious, because the implicit binders are empty even --- though the type might have free varaiables -mkEmptySigWcType ty = mkEmptyWildCardBndrs (mkEmptySigType ty) - -mkEmptySigType :: LHsType GhcRn -> LHsSigType GhcRn --- Dubious, because the implicit binders are empty even --- though the type might have free varaiables -mkEmptySigType lty@(L loc ty) = L loc $ case ty of -  HsForAllTy { hst_tele = HsForAllInvis { hsf_invis_bndrs = bndrs } -             , hst_body = body } -    -> HsSig { sig_ext = noExtField -             , sig_bndrs = HsOuterExplicit { hso_xexplicit = noExtField -                                           , hso_bndrs     = bndrs } -             , sig_body = body } -  _ -> HsSig { sig_ext   = noExtField -             , sig_bndrs = HsOuterImplicit{hso_ximplicit = []} -             , sig_body = lty } - -addClassContext :: Name -> LHsQTyVars GhcRn -> LSig GhcRn -> LSig GhcRn --- Add the class context to a class-op signature -addClassContext cls tvs0 (L pos (ClassOpSig _ _ lname ltype)) -  = L pos (TypeSig noExtField lname (mkEmptyWildCardBndrs (go_sig_ty ltype))) -  where -    go_sig_ty (L loc (HsSig { sig_bndrs = bndrs, sig_body = ty })) -       = L loc (HsSig { sig_ext = noExtField -                      , sig_bndrs = bndrs, sig_body = go_ty ty }) - -    go_ty (L loc (HsForAllTy { hst_tele = tele, hst_body = ty })) -       = L loc (HsForAllTy { hst_xforall = noExtField -                           , hst_tele = tele, hst_body = go_ty ty }) -    go_ty (L loc (HsQualTy { hst_ctxt = ctxt, hst_body = ty })) -       = L loc (HsQualTy { hst_xqual = noExtField -                         , hst_ctxt = add_ctxt ctxt, hst_body = ty }) -    go_ty (L loc ty) -       = L loc (HsQualTy { hst_xqual = noExtField -                         , hst_ctxt = add_ctxt (L loc []), hst_body = L loc ty }) - -    extra_pred = nlHsTyConApp Prefix cls (lHsQTyVarsToTypes tvs0) -    add_ctxt (L loc preds) = L loc (extra_pred : preds) - -addClassContext _ _ sig = sig   -- E.g. a MinimalSig is fine - -lHsQTyVarsToTypes :: LHsQTyVars GhcRn -> [LHsTypeArg GhcRn] -lHsQTyVarsToTypes tvs -  = [ HsValArg $ noLoc (HsTyVar noExtField NotPromoted (noLoc (hsLTyVarName tv))) -    | tv <- hsQTvExplicit tvs ] - --------------------------------------------------------------------------------- --- * Making abstract declarations --------------------------------------------------------------------------------- - - -restrictTo :: [Name] -> LHsDecl GhcRn -> LHsDecl GhcRn -restrictTo names (L loc decl) = L loc $ case decl of -  TyClD x d | isDataDecl d  -> -    TyClD x (d { tcdDataDefn = restrictDataDefn names (tcdDataDefn d) }) -  TyClD x d | isClassDecl d -> -    TyClD x (d { tcdSigs = restrictDecls names (tcdSigs d), -               tcdATs = restrictATs names (tcdATs d) }) -  _ -> decl - -restrictDataDefn :: [Name] -> HsDataDefn GhcRn -> HsDataDefn GhcRn -restrictDataDefn names defn@(HsDataDefn { dd_ND = new_or_data, dd_cons = cons }) -  | DataType <- new_or_data -  = defn { dd_cons = restrictCons names cons } -  | otherwise    -- Newtype -  = case restrictCons names cons of -      []    -> defn { dd_ND = DataType, dd_cons = [] } -      [con] -> defn { dd_cons = [con] } -      _ -> error "Should not happen" - -restrictCons :: [Name] -> [LConDecl GhcRn] -> [LConDecl GhcRn] -restrictCons names decls = [ L p d | L p (Just d) <- map (fmap keep) decls ] -  where -    keep d | any (\n -> n `elem` names) (map unLoc $ getConNames d) = -      case d of -        ConDeclH98 { con_args = args }    -> restrict_h98_args args -        ConDeclGADT { con_g_args = args } -> restrict_gadt_args args -      where -        restrict_h98_args :: HsConDeclH98Details GhcRn -> Maybe (ConDecl GhcRn) -        restrict_h98_args (PrefixCon _ _) = Just d -        restrict_h98_args (RecCon (L _ fields)) -          | all field_avail fields = Just d -          | otherwise = Just (d { con_args = PrefixCon noTypeArgs (field_types fields) }) -          -- if we have *all* the field names available, then -          -- keep the record declaration.  Otherwise degrade to -          -- a constructor declaration.  This isn't quite right, but -          -- it's the best we can do. - -        restrict_h98_args (InfixCon _ _) = Just d - -        restrict_gadt_args :: HsConDeclGADTDetails GhcRn -> Maybe (ConDecl GhcRn) -        restrict_gadt_args (PrefixConGADT _) = Just d -        restrict_gadt_args (RecConGADT (L _ fields)) -          | all field_avail fields = Just d -          | otherwise = Just (d { con_g_args = PrefixConGADT (field_types fields) }) -          -- see the comments for the RecCon case of `restrict_h98_args` above - -        field_avail :: LConDeclField GhcRn -> Bool -        field_avail (L _ (ConDeclField _ fs _ _)) -            = all (\f -> extFieldOcc (unLoc f) `elem` names) fs -        field_types flds = [ hsUnrestricted t | L _ (ConDeclField _ _ t _) <- flds ] - -    keep _ = Nothing - -restrictDecls :: [Name] -> [LSig GhcRn] -> [LSig GhcRn] -restrictDecls names = mapMaybe (filterLSigNames (`elem` names)) - - -restrictATs :: [Name] -> [LFamilyDecl GhcRn] -> [LFamilyDecl GhcRn] -restrictATs names ats = [ at | at <- ats , unL (fdLName (unL at)) `elem` names ] - -emptyHsQTvs :: LHsQTyVars GhcRn --- This function is here, rather than in HsTypes, because it *renamed*, but --- does not necessarily have all the rigt kind variables.  It is used --- in Haddock just for printing, so it doesn't matter -emptyHsQTvs = HsQTvs { hsq_ext = error "haddock:emptyHsQTvs" -                     , hsq_explicit = [] } - -  --------------------------------------------------------------------------------  -- * Filename mangling functions stolen from s main/DriverUtil.lhs.  -------------------------------------------------------------------------------- -  baseName :: ModuleName -> FilePath  baseName = map (\c -> if c == '.' then '-' else c) . moduleNameString @@ -283,13 +151,6 @@ indexHtmlFile = "doc-index.html"  indexJsonFile = "doc-index.json" - -moduleIndexFrameName, mainFrameName, synopsisFrameName :: String -moduleIndexFrameName = "modules" -mainFrameName = "main" -synopsisFrameName = "synopsis" - -  subIndexHtmlFile :: String -> String  subIndexHtmlFile ls = "doc-index-" ++ b ++ ".html"     where b | all isAlpha ls = ls @@ -363,7 +224,7 @@ quickJumpCssFile = "quick-jump.css"  getProgramName :: IO String -getProgramName = liftM (`withoutSuffix` ".bin") getProgName +getProgramName = fmap (`withoutSuffix` ".bin") getProgName     where str `withoutSuffix` suff              | suff `isSuffixOf` str = take (length str - length suff) str              | otherwise             = str @@ -372,25 +233,6 @@ getProgramName = liftM (`withoutSuffix` ".bin") getProgName  bye :: String -> IO a  bye s = putStr s >> exitSuccess - -dieMsg :: String -> IO () -dieMsg s = getProgramName >>= \prog -> die (prog ++ ": " ++ s) - - -noDieMsg :: String -> IO () -noDieMsg s = getProgramName >>= \prog -> hPutStr stderr (prog ++ ": " ++ s) - - -mapSnd :: (b -> c) -> [(a,b)] -> [(a,c)] -mapSnd _ [] = [] -mapSnd f ((x,y):xs) = (x,f y) : mapSnd f xs - - -mapMaybeM :: Monad m => (a -> m b) -> Maybe a -> m (Maybe b) -mapMaybeM _ Nothing = return Nothing -mapMaybeM f (Just a) = liftM Just (f a) - -  escapeStr :: String -> String  escapeStr = escapeURIString isUnreserved @@ -437,9 +279,9 @@ writeUtf8File filepath contents = withFile filepath WriteMode $ \h -> do      hSetEncoding h utf8      hPutStr h contents -withTempDir :: (ExceptionMonad m) => FilePath -> m a -> m a +withTempDir :: (MonadIO m, MonadMask m) => FilePath -> m a -> m a  withTempDir dir = bracket_ (liftIO $ createDirectory dir) -                            (liftIO $ removeDirectoryRecursive dir) +                           (liftIO $ removeDirectoryRecursive dir)  -----------------------------------------------------------------------------  -- * HTML cross references diff --git a/haddock-api/src/Haddock/Utils/Json.hs b/haddock-api/src/Haddock/Utils/Json.hs index e3c3dddc..2270a547 100644 --- a/haddock-api/src/Haddock/Utils/Json.hs +++ b/haddock-api/src/Haddock/Utils/Json.hs @@ -19,7 +19,7 @@ import Data.Char  import Data.Int  import Data.String  import Data.Word -import Data.List +import Data.List (intersperse)  import Data.Monoid  import Data.ByteString.Builder (Builder)  | 
