(Arne Babenhauserheide)
2014-02-09: merge default into releases releases 0.5 merge default into releases
diff --git a/.bugs/bugs b/.bugs/bugs --- a/.bugs/bugs +++ b/.bugs/bugs @@ -4,11 +4,12 @@ offer different and customizeable ways t Add a list of branches, heads and tags to the summary page. | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:0fde104c4206be8245ff0716ee2e91ea3971db8f, time:1319147651.17 include incoming commits, so I can easily check if I should pull a fork - and visitors can see what they can find in the fork. | owner:, open:False, id:14e7a48faa8965f947695744cc40d0f2bc25023b, time:1365863785.15 if b is used: a bugtracker: issue/<id>/<name> | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:1d631d51ff06b3bdca50e21da3d6a00bcb801c85, time:1319147632.52 +avoid writing and subsequently uploading all bugs on each push | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, id:1fc514f333292b9ffded1f7dbcbc9a9330666972, time:1391919333.98 add css classes and ids everywhere, so this can be styled with CSS. | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, id:2699812cf02c803fa338daf9ae039c43a30a0b5f, time:1322090683.01 get mtimes from the repo instead of querying the FTP server. We know which files were changed. | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:29210503551d0eafca67dda8d6fffbd40bf837dc, time:1319213074.57 FIX: revision 0 is omitted: change that :) | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:29396f1753e45b5a37ffa0ce04d96c876d6b6722, time:1319209563.68 parse the pushed repo, not the local one. | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, id:2c26d62b62e3656ebcce43e7a24f627594911fb5, time:1322115065.37 -create a beautiful default style sheet to make the static sites look good. | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, id:31a87798e30ccdaeefd028426222092e06bf20b1, time:1351793911.56 +create a beautiful default style sheet to make the static sites look good. | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:31a87798e30ccdaeefd028426222092e06bf20b1, time:1351793911.56 revisions more structured, as list or similar. | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, id:39cacfc83da6f6beecafdb745823d7f01018206b, time:1322159357.88 tags do not have a heading on the overview anymore | owner:, open:False, id:485d0b451f18b5eae517b34466622b0d52340d8e, time:1351620233.63 only write .statichgrepo print.css style.css and index.html when their data changed \(or \-\-force\) → read them and compare the contents. | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:4f02149269a60fca85aa040116b2789d98c906f2, time:1319212903.98 diff --git a/README.txt b/README.txt --- a/README.txt +++ b/README.txt @@ -4,7 +4,7 @@ Create and/or upload a static copy of th You can get it via `hg clone http://draketo.de/proj/hgsite/` -The main goal is sharing code with Mercurial on servers who only offer +The main goal is sharing code with Mercurial on servers which only offer FTP access and statically served files, while providing the same information as hg serve and full solutions like bitbucket and gitorious (naturally without the interactivity). diff --git a/staticsite.py b/staticsite.py --- a/staticsite.py +++ b/staticsite.py @@ -37,12 +37,19 @@ templates = { <html><head> <meta charset="utf-8" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <!--duplicate for older browsers--> - <link rel="stylesheet" href="style.css" type="text/css" media="screen" /> - <link rel="stylesheet" href="print.css" type="text/css" media="print" /> + <link href='http://fonts.googleapis.com/css?family=OFL+Sorts+Mill+Goudy+TT:regular,italic' rel='stylesheet' type='text/css' /> + <link rel="stylesheet" href="{relpath}style.css" type="text/css" media="screen" /> + <link rel="stylesheet" href="{relpath}print.css" type="text/css" media="print" /> <title>{title}</title> </head> <body> -<h1 id="maintitle">{reponame}</h1> +<div class="wrap"> +<div class="top group"> +<header id="maintitle">{reponame}</header> +<nav>{nav}</nav> +</div> +<div class="hr"> </div> +<div class="content"> """, "srchead": """<!DOCTYPE html> <html><head> @@ -55,19 +62,33 @@ templates = { <title>{filetitle}</title> </head> <body onload="prettyPrint()"> +<div class="wrap"> +<div class="content"> """, "forkhead": """<!DOCTYPE html> <html><head> <meta charset="utf-8" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <!--duplicate for older browsers--> - <link rel="stylesheet" href="style.css" type="text/css" media="screen" /> - <link rel="stylesheet" href="print.css" type="text/css" media="print" /> + <link href='http://fonts.googleapis.com/css?family=OFL+Sorts+Mill+Goudy+TT:regular,italic' rel='stylesheet' type='text/css' /> + <link rel="stylesheet" href="{relpath}style.css" type="text/css" media="screen" /> + <link rel="stylesheet" href="{relpath}print.css" type="text/css" media="print" /> <title>{forkname}</title> </head> <body> -<h1>{forkname} <small>(fork of <a href="../../">{reponame}</a>, found at {forkuri})</small></h1> +<div class="wrap"> +<div class="top group fullwidth"> +<header>{forkname} <small>(fork of <a href="../../">{reponame}</a>, found at {forkuri})</small></header> +</div> +<div class="hr"> </div> +<div class="content"> """, - "foot": "</body></html>\n", + "foot": """<div class="hrb"> </div><footer> + <p> + Site made with the <a href="http://draketo.de/proj/hgsite">hg staticsite extension</a>, + Design based on the site from <a href="https://stevelosh.com">Steve Losh</a> + </p> + </footer></div><!-- /content --></div><!-- /wrap--></body></html>\n""", + # this screenstyle is mostly from the wonderful site http://stevelosh.com and licensed under MIT "screenstyle": """ .bugnumbers { font-size: x-small; @@ -81,8 +102,490 @@ templates = { color: #00f; text-decoration: none; } +/* Copyright (c) 2008-2010 Steve Losh + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE.*/ +html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,header,nav,section,article,aside,footer{ + border:0;margin:0;outline:0;padding:0;background:transparent;vertical-align:baseline; +} +article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{ + display:block; +} +blockquote,q{ + quotes:none; +} +blockquote:before,blockquote:after,q:before,q:after{ + content:'';content:none; +} +header,nav,section,article,aside,footer{ + display:block; +} +html{ + overflow-y:scroll; +} +body{ + background:#fdfdfd;color:#353535;font:normal 18px/25px Palatino,"Palatino Linotype",serif;text-rendering:optimizeLegibility; +} +html>body{ + font-size:18px;line-height:25px; +} +img{ + display:inline-block;vertical-align:bottom; +} +h1,h2,h3,h4,h5,h6,strong,b,dt,th{ + font-weight:700; +} +address,cite,em,i,caption,dfn,var{ + font-style:italic; +} +h1{ + font-size:45px;line-height:50px;margin:25px 0; +} +h2{ + font-size:32px;line-height:50px;margin:25px 0; +} +h3{ + font-size:23px;line-height:25px;margin:25px 0; +} +h4{ + margin:0 0 22px;font-size:16px;line-height:22px; +} +h5{ + margin:0 0 22px;font-size:14px;line-height:22px; +} +h6{ + margin:0 0 22px;font-size:12px;line-height:22px; +} +p,ul,ol,dl,blockquote,pre{ + margin:0 0 25px; +} +li ul,li ol{ + margin:0; +} +ul{ + list-style:outside disc; +} +ol{ + list-style:outside decimal; +} +li{ + margin:0 0 0 44px; +} +dd{ + padding-left:25px; +} +blockquote{ + padding:0 25px; +} +a{ + text-decoration:underline; +} +a:hover{ + text-decoration:none; +} +abbr,acronym{ + border-bottom:1px dotted;cursor:help; +} +del{ + text-decoration:line-through; +} +ins{ + text-decoration:overline; +} +sub{ + font-size:14px;line-height:25px;vertical-align:sub; +} +sup{ + font-size:14px;line-height:25px;vertical-align:super; +} +tt,code,kbd,samp,pre{ + font-size:14px;line-height:25px;font-family:Menlo,Monaco,Consolas,"Courier New",monospace; +} +table{ + border-collapse:collapse;border-spacing:0;margin:0 0 1.5em; +} +caption{ + text-align:left; +} +th,td{ + padding:.25em .5em; +} +tbody td,tbody th{ + border:1px solid #222; +} +tfoot{ + font-style:italic; +} +fieldset{ + clear:both; +} +legend{ + padding:0 0 1.286em;font-size:1.167em;font-weight:700; +} +fieldset fieldset legend{ + padding:0 0 1.5em;font-size:1em; +} +* html legend{ + margin-left:-7px; +} +*+html legend{ + margin-left:-7px; +} +form .field,form .buttons{ + clear:both;margin:0 0 1.5em; +} +form .field label{ + display:block; +} +form ul.fields li{ + list-style-type:none;margin:0; +} +form ul.inline li,form ul.inline label{ + display:inline; +} +form ul.inline li{ + padding:0 .75em 0 0; +} +input.radio,input.checkbox{ + vertical-align:top; +} +label,button,input.submit,input.image{ + cursor:pointer; +} +* html input.radio,* html input.checkbox{ + vertical-align:middle; +} +*+html input.radio,*+html input.checkbox{ + vertical-align:middle; +} +textarea{ + overflow:auto; +} +input.text,input.password,textarea,select{ + margin:0;font:1em/1.3 Helvetica,Arial,"Liberation Sans","Bitstream Vera Sans",sans-serif;vertical-align:baseline; +} +input.text,input.password,textarea{ + border:1px solid #444;border-bottom-color:#666;border-right-color:#666;padding:2px; +} +* html button{ + margin:0 .34em 0 0; +} +*+html button{ + margin:0 .34em 0 0; +} +form.horizontal .field{ + padding-left:150px; +} +form.horizontal .field label{ + display:inline;float:left;width:140px;margin-left:-150px; +} +img.left{ + display:inline;float:left;margin:0 1.5em .75em 0; +} +img.right{ + display:inline;float:right;margin:0 0 .75em .75em; +} +.group:after{ + content:".";display:block;height:0;clear:both;visibility:hidden; +} + +html{ + overflow-y:scroll; +} +body{ + text-rendering:optimizeLegibility;color:#222222;position:relative; +} +body a{ + text-decoration:none;color:#e50053; +} +body a:hover{ + text-decoration:underline; +} +body h1,body h2,body h3,body h4,body h5,body h6{ + font-family:'OFL Sorts Mill Goudy','OFL Sorts Mill Goudy TT',serif;font-weight:normal; +} +body h1 a,body h2 a,body h3 a,body h4 a,body h5 a,body h6 a{ + color:#222222; +} +body h1 a:hover,body h2 a:hover,body h3 a:hover,body h4 a:hover,body h5 a:hover,body h6 a:hover{ + color:#e50053;text-decoration:none; +} +body h1 .amp,body h2 .amp,body h3 .amp,body h4 .amp,body h5 .amp,body h6 .amp{ + font-style:italic; +} +body h1{ + font-size:45px;line-height:50px;margin:25px 0; +} +body h2{ + font-size:32px;line-height:50px;margin:25px 0; +} +body h3{ + font-size:23px;line-height:25px;margin:25px 0; +} +body h4{ + font-size:18px;line-height:25px;margin:25px 0; +} +body code,body pre{ + font-family:Consolas,Menlo,"Courier New",monospace;font-size:14px; +} +body .codehilite code,body .codehilite pre{ + font-family:Consolas,Menlo,"Courier New",monospace;font-size:16px;line-height:25px;overflow-x:auto;border:1px solid #d5d5d5;border-left:10px solid #d5d5d5;background-color:#fafafa;padding:11px 15px 12px;margin-left:-25px; +} +body .codehilite pre::-webkit-scrollbar{ + height:25px; +} +body .codehilite pre::-webkit-scrollbar-button:start,body .codehilite pre::-webkit-scrollbar-button:end{ + display:none; +} +body .codehilite pre::-webkit-scrollbar-track-piece{ + background-color:#eee; +} +body .codehilite pre::-webkit-scrollbar-thumb{ + background-color:#bbb;border:7px solid #eee;-webkit-background-clip:padding-box;-webkit-border-radius:12px; +} +body p code,body li code,body table code{ + border:1px solid #ccc;background-color:#fafafa;font-size:13px;padding:1px 3px;line-height:20px;margin:0;white-space:nowrap; +} +body .wrap{ + width:612px;margin:0 auto;margin-bottom:5em; +} +body .wrap .top header{ + float:left;font-family:'OFL Sorts Mill Goudy','OFL Sorts Mill Goudy TT',serif;font-size:23px;line-height:50px;text-transform:lowercase;padding-left:2px;width:210px; +} +body .wrap .top .fullwidth header{ + float:left;font-family:'OFL Sorts Mill Goudy','OFL Sorts Mill Goudy TT',serif;font-size:23px;line-height:50px;text-transform:lowercase;padding-left:2px;width:100%; +} +body .wrap .top header .amp{ + font-style:italic; +} +body .wrap .top header a{ + color:#222222; +} +body .wrap .top header a:hover{ + color:#e50053; +} +body .wrap .top nav{ + /* reduced font size and/or line height compared to steve losh (18px/50px), + because we can have a long lis tof forks and use <sup> elements for the bugs.*/ + font:normal 18px/35px 'OFL Sorts Mill Goudy','OFL Sorts Mill Goudy TT',serif;text-align:right;text-transform:lowercase;padding-right:2px;width:398px;float:left; +} +body .wrap .top nav .sep{ + padding:0 4px;color:#666; +} +body .wrap .hr{ + margin-top:-12px;margin-bottom:37px;height:25px;background:transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAmQAAAAZCAIAAAAQUKXdAAADAklEQVR42u3c3UtTcRzHcf+nIOquu266TIICsceLLpKISKPQqOxGgkgjioouyrIUzbJI0xKV0CwpdW7HTQ+6ubNH3dzc3JQ+emSu0a1u4PvlkMnYLg7i2+/5/c4pWwNKW1ZfAFBUZRwClLi2n4+i8VAmk+FQACCWwP/Gymy2oacqGgun02k954AAIJZAIQ2UN7tOxePxZDLJcAmAWAKFGnouDLt7nwzULy0tKZZMlgCIJVDofMuhM80Hfhj9iuXKygqxBEAsgbX19fXcc6XxRlflpdYjVsBSLLVmyfEBQCyx1zNpUyW/ONqcC2OqY1Pf1ebvjcFgUGuWLFgCIJaglHYp14amP518se/sq4OGd+Lht1rX3MTi4mIqleIcLABiCWK5Fcs3ow8USz1qOyvudl+MRCLLy8urq6scJQDEEpRyK5ZPh+rtWOrx+VdrOBxmaw+A4sdSC0IOYFdMbXI6nS6XyzAMt9s9Ozs7Pz/vtyxFUQuTiUTi9XCjXcq6d5V61efzBQIBv9/v9XpN0/R4PHqj3q4PsT+NowpgpymUTJYorcmyc+y5Snn65f6RyUFlUvm0x8r8jbIAsNuTpRaE/MCusSw9RCHUP2saKKPRaCwWUxS1i0c7YFtGmhTLx19va+LUq/r91EsaOrXNRz+GQiG90dr8kI0HAOw8/SFiskTxJ0t9T2dS0URIQ+SzwTtVbw/PzLnzVytzcycAFGey5BCgBGKZvf7+hG7W88ccruko7/7dpgkytwk2/yQtABBL7FHB2IK9qUcz5a2ucyqlfW1lrqaUEgCxxF7nCUzZsaxpP2aYTp2A1TqlfcsexkoAxBLYMGB8VCmr28sd7nFt3tF2Hk7AAiCWwDZt4bnfd6W646jLdGiDa/4908kkAGIJbJj2j1/rPD7jM3QliUrJbWABEEvgH5O+0boPFXMBj321JaUEQCyBbeG4pdvA3uu97I/4NFDqQhGdfaWUAIglsG3U7B/x9GnXq337HkoJgFgChXRliE66JpNJ3aaHUgIocX8BBfw+1JXTYZkAAAAASUVORK5CYII=')/*../images/hr.png*/ top left no-repeat; +} +body .wrap .hrb{ + height:25px;margin-top:50px;background:transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAmQAAAAZCAIAAAAQUKXdAAADMklEQVR42u3c30tTcRjHcf+nIOquu266TIICsZ8XXSQRkUahUdmNBGFGFBVdlGI1NMsiTUtUSjOk1LUfOqZsnrOfujnd3Mw+eiDn8iZwY2Pvl2NseLaLhwc/Pud8z7diDQCQJaMfYLsKSgAA2WzfH0TjoXQ6TSlAWALATmNlJtPUWxONhVOplF5TEBCWAJBLA+X17hPxeHx5eZnhEoQlAORq6j03Mt33aLBxcXFRYclkCcISAHKdbT9wqnXfN9eAwnJlZYWwBGGJYvR7J5QFeW25v68Vjde6qy+8OmQGTIWlrllSHxCWKIGYJC9RgK5TSn602xzz40rHlv7LrV/uBoNBXbPkgiUIS5RSUpKXyGdSrg273x9/tud0236Xb/L+53rn3OTCwkIymeQcLAhLlF5YkpfIR8vp9YuxewpLPeq7qm73nI9EIktLS6urq1QJhCWKNynXsxCWKEBYPh5utMJSjw/jtnA4zNIe7BCWOjtvBwri1yaHw+F0OqkGCt91brfb4/HMzs76/f5QKKRVPBoi2742W0nZ8Lra6/UahqG/ioFAQMfoSB2vT+mz+gbrqyhpGVJLMFmiiCbL9X8wWSKvLae3XeNPlZQnn+8dnRpSRiYSCWuspOuwbbLUP1YGUDCmqYdQCRS+6zQfaKDUVUlrptS2A1oB2z7aorB8+Ommz+fTrxKb9Fsdo7c6Xp8yN7/BoG/LlfqByRJMlii7ltNzKp2MJjZ2S38ydKvm5UHP3HT21Uq6DrmTJSVA8YQlC3xQKJmrb45ps56f3pG6zsqeHzZNkJoerHsraTkQliiBvOS+EeRbMDZvLerRTHmj+4yS0rq3MqchKRQISxCWKF8zpt0Ky7qOIy6vQydgdZ2SsRKEJUo7L6kPdteg652Ssraj0j49ocU72tzO2oWAlgNhiZKMTGqCXaclPM39l2o7Dzu9di1wzd4zna4DYQkAG9zGxJWuox6/S/eEKCnZBhaEJQBsM+Ufa3hbNReYiUajsViMpARhCQBbwnFT28De6btoRPzWpgQ6+0pSgrAEgC1j3oHRmX6tetVAqWeSEoQlAOTSnSE66aot7rRND0mJ//UHiLRAti+ZCq0AAAAASUVORK5CYII=')/*../images/hrb.png*/ top left no-repeat; +} +body .wrap footer{ + text-align:center; +} +body .wrap footer p{ + font-size:14px;font-style:italic;line-height:50px;margin-bottom:0px; +} +body .wrap footer .rochester-made img{ + opacity:0.7;padding:5px 20px; +} +hr{ + border:none;background:#ccc;height:1px;margin-bottom:24px; +} +.splash{ + color:#454545;text-align:center;font:normal 27px/32px 'OFL Sorts Mill Goudy','OFL Sorts Mill Goudy TT',serif;margin-bottom:-1px;padding-top:0; +} +.splash p{ + margin-bottom:24px; +} +.splash .amp{ + font-style:italic; +} +.splash .fn{ + color:#454545;text-decoration:none; +} +.splash .fn:hover{ + color:#e50053;text-decoration:none; +} +.splash .fn .last-name{ + display:none; +} +.section-listing{ + margin-bottom:-50px; +} +.section-listing ol{ + list-style-type:none; +} +.section-listing ol li{ + float:left;width:281px;height:150px;margin:0;text-align:center; +} +.section-listing ol li a{ + font:normal 23px/32px 'OFL Sorts Mill Goudy','OFL Sorts Mill Goudy TT',serif;color:#222222;display:block; +} +.section-listing ol li a:hover{ + color:#e50053;text-decoration:none; +} +.section-listing ol li span.snip{ + font-size:18px;color:#333;font-family:'OFL Sorts Mill Goudy','OFL Sorts Mill Goudy TT',serif;line-height:25px;font-style:italic; +} +.section-listing ol li .amp{ + font-style:italic; +} +.section-listing ol li:nth-child(odd){ + margin-right:25px; +} +.section-listing ol li:nth-child(even){ + margin-left:25px; +} +blockquote{ + border:1px solid #ccc;background-color:#fafafa;padding:11px 15px 12px;margin-left:2em;overflow:auto; +} +blockquote p:last-child{ + margin-bottom:0; +} +span.dquo{ + margin-left:-0.23em; +} +#leaf-stats p{ + color:#666;margin-top:-22px;margin-bottom:22px; +} +#leaf-content img{ + display:block;margin:25px auto 26px;border:11px solid #e5e5e5;padding:1px;background:black;max-width:590px; +} +#leaf-content img.left,#leaf-content img.right{ + border:none;background:none;padding:none; +} +#leaf-content img.left{ + margin:0 1.5em 1em 0; +} +#leaf-content img.right{ + margin:0 0 .75em 1em; +} +#leaf-content .gallery img{ + background:none;padding:0;border:none;display:inline;margin-bottom:25px;margin-right:25px; +} +#leaf-content .toc ul{ + list-style:none; +} +#leaf-content .toc ul:first-child>li{ + margin-left:0em; +} +#leaf-content table{ + padding:0px;margin-top:-8px;margin-bottom:25px; +} +#leaf-content table tr{ + margin:0px;padding:0px; +} +#leaf-content table tr td,#leaf-content table tr th{ + margin:0px;padding:5px 5px;line-height:23px; +} +#leaf-content table tr td{ + border:1px solid #666; +} +#leaf-content.with-diagrams img{ + display:block;margin:25px auto;padding:0;background:none;border:none; +} +.print-links{ + display:none; +} +img.self{ + border:none;padding:0;margin:0;margin-right:-108px;margin-top:-15px;margin-left:30px;margin-bottom:20px; +} +div#cboxCurrent{ + bottom:-30px;font-size:17px;font-weight:normal;left:60px; +} +div.screenshots img{ + max-width:580px; +} +#scrolling-header{ + color:#999;font-size:23px;font-style:italic;font:italic 23px 'OFL Sorts Mill Goudy','OFL Sorts Mill Goudy TT',serif;line-height:30px;position:fixed;top:75px;text-align:right;width:180px; +} +.flattr{ + float:right;padding-top:1px; +} """, - "printstyle": """ """, + # this printstyle is from the wonderful site http://stevelosh.com and licensed under MIT + "printstyle": """ +/*Copyright (c) 2008-2010 Steve Losh + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE.*/ + +body{ +font:normal 10pt/1.25 Palatino,"Palatino Linotype";text-rendering:optimizeLegibility; +} +nav,header,.toc{ +display:none; +} +#leaf-title a{ +text-decoration:none;color:black; +} +#leaf-content ul.print-links{ +display:block;font-size:1em;list-style-type:none;margin-left:0em; +} +#leaf-content ul.print-links a{ +text-decoration:none; +} +#leaf-content code,#leaf-content pre{ +font:normal 9pt Menlo,Monaco,Consolas,"Courier New",Courier,monospace; +} +#leaf-content img{ +display:block;margin-left:auto;margin-right:auto;border:1.43em solid #e5e5e5;padding:1px;background:black; +} +#leaf-content img.left,#leaf-content img.right{ +border:none;background:none;padding:none; +} +#leaf-content img.left{ +margin:0 1.5em 1em 0;float:left; +} +#leaf-content img.right{ +margin:0 0 .75em 1em;float:right; +} +div#leaf-content.with-diagrams img{ +display:block;margin-left:auto;margin-right:auto;background:none;border:none; +} +span.amp{ +font-family:"Palatino","Constantia","Palatino Linotype",serif;font-style:italic; +} +.flattr{ +display:none; +} +a{ +text-decoration:underline;color:#c06; +} +footer{ +display:none; +} +""", "manifesthead": """<h2>""" + _("Commit (click to see the diff)")+""": <a href='../../commit/{hex}.html'>{hex}</a></h2> <p>{desc}</p><p>{user}</p> <h2>""" + _("Diffstat") + """</h2> @@ -186,9 +689,9 @@ def parsereadme(filepath, truncated=Fals with open(filepath) as r: readme = r.read() if truncated: - return "<pre>" + "\n".join(readme.splitlines()[:5]) + "</pre>" + return "<pre style=\"white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;\">" + "\n".join(readme.splitlines()[:5]) + "</pre>" else: - return "<pre>" + readme + "</pre>" + return "<pre style=\"white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;\">" + readme + "</pre>" def overviewlogstring(ui, repo, revs, template=templates["commitlog"]): """Get the string for a log of the given revisions for the overview page.""" @@ -204,8 +707,39 @@ def writeoverview(ui, repo, target, name """Create the overview page""" ui.debug("[staticsite] writeoverview: header\n") overview = "" - # get the title - overview += templates["head"].replace("{reponame}", name).replace("{title}", name) + # start with the nav + nav = "" + # now the links to the log and the files. + nav += "<a href='commits'>" + _("changelog") + "</a> - <a href='src/" + repo["tip"].hex() + "/'>" + _("files") + "</a>" + # and the bugs + openbugs, resolvedbugs = getbugs(ui, repo) + if openbugs or resolvedbugs: + nav += " - <a href=\"bugs\">" + _("bugs") + "</a>" + if openbugs: + nav += " <span class=\"bugnumbers\">(<span class=\"openbugnumber\"><a href=\"bugs#open\">" + str(len(openbugs)) + "!</a></span> " + else: + nav += " <span class=\"bugnumber openbugnumberzero\">0</span>" + nav += "<span class=\"bugnumber resolvedbugnumber\"><a href=\"bugs#resolved\">" + str(len(resolvedbugs)) + "√</a></span>)</span>" + + # and the forks + ui.debug("[staticsite] writenav: header: forks\n") + forks = getforkinfo(ui, target) + if forks: + nav += " - " + _("forks: ") + for forkname, forkuri in forks.items(): + ui.debug("[staticsite] writenav: fork: " + forkname + ": " + forkuri + "\n") + ui.debug("[staticsite] writenav: forks: getforkdir\n") + nav += "<a href='" + getforkdir(target, forkname) + "'>" + forkname + "</a> " + ui.debug("[staticsite] writenav: forks: getincoming\n") + incoming, fn, localother = getincoming(ui, repo, otheruri=forkuri, othername=forkname) + nav += "<small>(" + str(len(incoming)) + ui.debug("[staticsite] writenav: forks: getoutgoing\n") + outgoing, fn, localother = getoutgoing(ui, repo, otheruri=forkuri, othername=forkname) + nav += "<small>↓↑</small>" + str(len(outgoing)) + ")</small> " + + + # embed in the overview via the template + overview += templates["head"].replace("{reponame}", name).replace("{title}", name).replace("{nav}", nav).replace("{relpath}", "./") # add a short identifier from the first line of the readme, if it # exists # TODO: Parse different types of readme files readme = name @@ -217,35 +751,6 @@ def writeoverview(ui, repo, target, name overview += readme_intro overview += "</div>" break - # now the links to the log and the files. - overview += "\n<p id='nav'><a href='commits'>" + _("changelog") + "</a> | <a href='src/" + repo["tip"].hex() + "/'>" + _("files") + "</a>" - # and the bugs - openbugs, resolvedbugs = getbugs(ui, repo) - if openbugs or resolvedbugs: - overview += " | <a href=\"bugs\">" + _("bugs") + "</a>" - if openbugs: - overview += " <span class=\"bugnumbers\">(<span class=\"openbugnumber\"><a href=\"bugs#open\">" + str(len(openbugs)) + "!</a></span> " - else: - overview += " <span class=\"bugnumber openbugnumberzero\">0</span>" - overview += "<span class=\"bugnumber resolvedbugnumber\"><a href=\"bugs#resolved\">" + str(len(resolvedbugs)) + "√</a></span>)</span>" - - # and the forks - ui.debug("[staticsite] writeoverview: header: forks\n") - forks = getforkinfo(ui, target) - if forks: - overview += " | " + _("forks: ") - for forkname, forkuri in forks.items(): - ui.debug("[staticsite] writeoverview: fork: " + forkname + ": " + forkuri + "\n") - ui.debug("[staticsite] writeoverview: forks: getforkdir\n") - overview += "<a href='" + getforkdir(target, forkname) + "'>" + forkname + "</a> " - ui.debug("[staticsite] writeoverview: forks: getincoming\n") - incoming, fn, localother = getincoming(ui, repo, otheruri=forkuri, othername=forkname) - overview += "<small>(" + str(len(incoming)) - ui.debug("[staticsite] writeoverview: forks: getoutgoing\n") - outgoing, fn, localother = getoutgoing(ui, repo, otheruri=forkuri, othername=forkname) - overview += "<small>↓↑</small>" + str(len(outgoing)) + ")</small> " - - overview += "</p>" ui.debug("[staticsite] writeoverview: shortlog\n") # now add the 5 most recent log entries @@ -356,7 +861,7 @@ def writelog(ui, repo, target, name): d = commits logs.append([os.path.join(d, "index.html"), ""]) - logs[-1][-1] += templates["head"].replace("{reponame}", "<a href='../'>"+name+"</a>").replace("{title}", name) + logs[-1][-1] += templates["head"].replace("{reponame}", "<a href='../'>"+name+"</a>").replace("{title}", name).replace("{nav}", "").replace("{relpath}", "../") for c in range(ck*100+1, min(len(repo.changelog)+1, (ck+1)*100)): ctx = repo.changectx(str(-c)) t.show(ctx) @@ -510,7 +1015,8 @@ def getforkdata(ui, repo, target, name, html = templates["forkhead"].replace( "{forkname}", forkname).replace( "{reponame}", name).replace( - "{forkuri}", safeuri(forkuri)) + "{forkuri}", safeuri(forkuri)).replace( + "{relpath}", "../../") # prepare the log templater t = cmdutil.changeset_templater(ui, repo, patch=False, diffopts=None, mapfile=None, buffered=False) @@ -591,7 +1097,7 @@ def writecommitsforchlist(ui, repo, targ if not force and os.path.isfile(cpath): continue with open(cpath, "w") as cf: - cf.write(templates["head"].replace("{reponame}", "<a href='../'>"+name+"</a>").replace("{title}", name)) + cf.write(templates["head"].replace("{reponame}", "<a href='../'>"+name+"</a>").replace("{title}", name).replace("{nav}", "").replace("{relpath}", "../")) ui.pushbuffer() t.show(ctx) cf.write(ui.popbuffer()) @@ -639,20 +1145,26 @@ def writebugs(ui, repo, target, name): content += "<li><a href=\"" + bug.fullid + ".html\">" + bug.shortid + "</a> - " + htmlescape(bug.description) + "</li>\n" content += "</ul>\n" with open(bugslist, "w") as f: - f.write(templates["head"].replace("{reponame}", "<a href='../'>"+name+"</a>").replace("{title}", name)) + f.write(templates["head"].replace("{reponame}", "<a href='../'>"+name+"</a>").replace("{title}", name).replace("{nav}", "").replace("{relpath}", "../")) f.write(content) f.write(templates["foot"].replace("{reponame}", "<a href='../'>"+name+"</a>")) # write all bug details for bug in openbugs + resolvedbugs: - bugsfile = bugslist = os.path.join(bugdir, bug.fullid + ".html") - content = "<h2>" + bug.description + "</h2>\n" - content += "<pre>" + bug.details + "</pre>\n" - content += "<hr>" - content += "- <a href=\"index.html\">" + _("all bugs") + "</a> -" - with open(bugsfile, "w") as bf: - bf.write(templates["head"].replace("{reponame}", "<a href='../'>"+name+"</a>").replace("{title}", name)) - bf.write(content) - bf.write(templates["foot"].replace("{reponame}", "<a href='../'>"+name+"</a>")) + bugsfile = os.path.join(bugdir, bug.fullid + ".html") + body = "<h2>" + bug.description + "</h2>\n" + body += "<pre>" + bug.details + "</pre>\n" + body += "<hr>" + body += "- <a href=\"index.html\">" + _("all bugs") + "</a> -" + content = templates["head"].replace("{reponame}", "<a href='../'>"+name+"</a>").replace("{title}", name).replace("{nav}", "").replace("{relpath}", "../") + content += body + content += templates["foot"].replace("{reponame}", "<a href='../'>"+name+"</a>") + try: + if not contentequals(bugsfile, content): + raise Exception("bugfile content does not match content to write. Needs overwriting.") + except Exception as e: # generic exception: If anything went wrong, we need to write the file. + print "Overwriting bugs file", bugsfile, "; Reason:", e + with open(bugsfile, "w") as bf: + bf.write(content) def escapename(filename): """escape index.html as .index.html and .ind… as ..ind… and so fort.""" @@ -755,10 +1267,11 @@ def writesourcetreeforchlist(ui, repo, t try: os.makedirs(os.path.dirname(filepath)) except OSError: pass # exists + content = templates["head"].replace("{reponame}", "<a href='../../'>"+name+"</a>").replace("{title}", name).replace("{nav}", "").replace("{relpath}", "../../") + content += createindex(ui, repo, target, ctx) + content += templates["foot"].replace("{reponame}", "<a href='../../'>"+name+"</a>") with open(filepath, "w") as f: - f.write(templates["head"].replace("{reponame}", "<a href='../../'>"+name+"</a>").replace("{title}", name)) - f.write(createindex(ui, repo, target, ctx)) - f.write(templates["foot"].replace("{reponame}", "<a href='../../'>"+name+"</a>")) + f.write(content) def writesourcetree(ui, repo, target, name, force, rawfiles=False): @@ -851,6 +1364,8 @@ def addrepo(ui, repo, target, bookmarks, def upload(ui, repo, target, ftpstring, force): """upload the repo to the FTP server identified by the ftp string.""" + if ftpstring.startswith("ftp://"): + ftpstring = ftpstring[len("ftp://"):] try: user, password = ftpstring.split("@")[0].split(":") serverandpath = "@".join(ftpstring.split("@")[1:])