BlogLiterately 0.3 → 0.4
raw patch · 11 files changed
+1703/−1338 lines, 11 filesdep +blaze-htmldep +processdep +transformersdep −haskell98dep −xhtmldep ~HaXmldep ~basedep ~cmdargssetup-changednew-uploader
Dependencies added: blaze-html, process, transformers
Dependencies removed: haskell98, xhtml
Dependency ranges changed: HaXml, base, cmdargs, haxr, hscolour, pandoc, parsec
Files
- BlogLiterately.cabal +38/−158
- CHANGES +16/−0
- LICENSE +674/−674
- Setup.hs +4/−4
- doc/BlogLiteratelyDoc.lhs +258/−0
- hscolour.css +0/−6
- kate.css +0/−23
- src/BlogLiterately.lhs +668/−473
- style/hs-style +16/−0
- style/hscolour.css +6/−0
- style/kate.css +23/−0
BlogLiterately.cabal view
@@ -1,158 +1,38 @@-Name: BlogLiterately -Version: 0.3 -Synopsis: A tool for posting Haskelly articles to blogs - -Description: BlogLiterately is a tool for uploading web log posts to web log servers - that support the MetaWeblog API (such as WordPress-based blogs and many - others). Blog posts to be published via BlogLiterately are written in - markdown [1] format, with extensions supported by pandoc [2]. Posts may be - actual 'bird-style' literate Haskell files, with commentary in markdown. - Code segments (including actual source lines from literate haskell files, - as well as markdown code blocks) may be syntax-highlighted in the resulting - HTML that is posted to the blog. There are two types (two different - libraries used) of formatting available for formatting code segments. - . - * Hscolour (for formatting Haskell code segments) - . - * highlighting-kate (for formatting Haskell and non-haskell segments) - . - The Markdown webpage has information about markdown formatting options, - and the Pandoc website has information about the extensions supported. - BlogLiterately extends the notation a bit further, for specifying code - segments. In basic markdown, A code segment is set off from normal - text via indentation, e.g.: - . - > -- This is a code segment but the tool doesn't know what kind! - > foo :: String -> String - . - Pandoc offers another way to specify a code segment (replace the - square braces with curly braces, haddock/hackage mangles them): - . - > ~~~~ [ .haskell ] - > -- This is a code segment, and the tool knows it's Haskell! - > foo :: String -> String - > ~~~~ - . - BlogLiterately lets you specify a Haskell segment this way (this is - just a normal markdown indented code block with an extra tag at - the top. In either the above way of specifying the type of code - in the block, you may specify other kinds of code besides haskell, - e.g. cpp, bash, java, ml, eiffel, etc.): - . - > [haskell] - > -- This is a code segment, and the tool knows it's Haskell! - > foo :: String -> String - . - Once you have written your markdown file, you can run the tool, specifying how - you want it highlighted. You can specify different highlighting modes for - the haskell segments and the other code segments. If using hscolour, you - can specify that the highlighting be done 'inline' via CSS 'style' - attributes. You can use the default styling (which is similar to source - code in documentation on hackage) or you can specify a configuration file - which looks something like this: - . - > [("hs-keyword","color: blue; font-weight: bold;") - > , ("hs-keyglyph","color: red;") - > , ("hs-layout","color: red;") - > , ("hs-comment","color: green;") - > , ("hs-conid", "") - > , ("hs-varid", "") - > , ("hs-conop", "") - > , ("hs-varop", "") - > , ("hs-str", "color: teal;") - > , ("hs-chr", "color: teal;") - > , ("hs-number", "") - > , ("hs-cpp", "") - > , ("hs-selection", "") - > , ("hs-variantselection", "") - > , ("hs-definition", "")] - . - It has to be (readable as) a Haskell value of type [(String,String)], - and it will only have an effect if you use the above class names (e.g. - 'hs-keyword' to specify a style for Haskell keywords). - . - With highlighting-kate (always) and with hscolour - (optionally), the style for syntax segments is specified using 'class' - attributes, so the stylesheet must be provided separately. Sample - stylesheets are provided in the package archive file. - . - To use the highlighting-kate, you must (re)install Pandoc with highlighting - enabled, like so: - . - > cabal install -fhighlighting pandoc - . - or - . - > cabal install --reinstall -fhighlighting pandoc - . - (If you have already installed BlogLiterately, you must reinstall that - as well). - . - The options for BlogLiterately are, I hope, self-explanatory (given the - above background!). Note that if Pandoc isn't installed with highlighting - enabled, there will be fewer options (no -kate options): - . - > BlogLierately v0.3, (C) Robert Greayer 2009 - > This program comes with ABSOLUTELY NO WARRANTY - > - > - > BlogLiterately [FLAG] URL USER PASSWORD TITLE FILE - > - > -? --help[=FORMAT] Show usage information (optional format) - > -V --version Show version information - > -v --verbose Higher verbosity - > -q --quiet Lower verbosity - > -t --test do a test-run: html goes to stdout, is not posted - > -s --style=FILE Style Specification (for --hscolour-icss) - > --hscolour-icss hilight haskell: hscolour, inline style (default) - > --hscolour-css hilight haskell: hscolour, separate stylesheet - > --hs-nohilight no haskell hilighting - > --hs-kate hilight haskell with highlighting-kate - > --other-code-kate hilight other code with highlighting-kate - > --publish Publish post (otherwise it's uploaded as a draft) - > --category=VALUE post category (can specify more than one) - > -b --blogid=VALUE Blog specific identifier (default=default) - > --postid=VALUE Post to replace (if any) - . - . - To post to a WordPress blog, the command is: - . - > BlogLiterately http://blogurl.example.com/xmlrpc.php \ - > myname mypasswd "Sample" Sample.lhs - . - (which creates a new post). If, for example, the post id of that post - (which BlogLiterately prints when it uploads a new post) was '37', then - to update the post, the command would be: - . - > BlogLiterately --postid=37 http://blogurl.example.com/xmlrpc.php \ - > myname mypasswd "Sample" Sample.lhs - . - and the post will be updated with the new text. - . - References: - . - 1. <http://daringfireball.net/projects/markdown/> - . - 2. <http://johnmacfarlane.net/pandoc/> - -Cabal-Version: >= 1.5 -Homepage: none -License: GPL -License-file: LICENSE -Category: Web -Copyright: Copyright (c) Robert Greayer 2008. -Author: Robert Greayer <robgreayer@yahoo.com> -Maintainer: Robert Greayer <robgreayer@yahoo.com> -Stability: experimental -Build-Type: Simple -Tested-With: GHC ==6.10.4 -Extra-Source-Files: hscolour.css - kate.css -Executable BlogLiterately - Build-Depends: base >= 4.0 && < 4.3, haskell98, parsec >= 2.1.0.0 && < 3, - HaXml >= 1.20 && < 1.21, utf8-string >= 0.3 && < 0.4, - hscolour >= 1.15 && < 1.17, xhtml >= 3000.2 && < 3000.3, cmdargs >= 0.1 && < 0.2, - haxr >= 3000.2.1 && < 3000.6, pandoc >= 1.2 && < 1.6 - Main-Is: BlogLiterately.lhs - Hs-Source-Dirs: src - Ghc-Options: -fwarn-unused-imports +Name: BlogLiterately+Version: 0.4+Synopsis: A tool for posting Haskelly articles to blogs+Description: Write blog posts in Markdown format, then use BlogLiterately+ to do syntax highlighting, format ghci sessions, and upload+ to any blog supporting the metaWeblog API (such as Wordpress).+ .+ See <http://byorgey.wordpress.com/blogliterately/> for complete+ documentation.+Cabal-Version: >= 1.6+Homepage: http://byorgey.wordpress.com/blogliterately/+License: GPL+License-file: LICENSE+Category: Web+Copyright: Copyright (c) Robert Greayer 2008-2010, Brent Yorgey 2012+Author: Robert Greayer <robgreayer@yahoo.com>+Maintainer: Brent Yorgey <byorgey@cis.upenn.edu>+Stability: experimental+Build-Type: Simple+Tested-With: GHC ==7.4.1+Extra-Source-Files: CHANGES+ doc/BlogLiteratelyDoc.lhs+ style/*.css+ style/hs-style+Source-repository head+ type: darcs+ location: http://patch-tag.com/r/byorgey/BlogLiterately++Executable BlogLiterately+ Build-Depends: base >= 4.0 && < 4.6, process >= 1.1 && < 1.2,+ transformers >= 0.3 && < 0.4, parsec >= 3 && < 3.2,+ HaXml >= 1.22 && < 1.23, utf8-string >= 0.3 && < 0.4,+ hscolour >= 1.20 && < 1.21, blaze-html >= 0.5 && < 0.6,+ cmdargs >= 0.9.5 && < 0.10,+ haxr >= 3000.8 && < 3000.9, pandoc >= 1.9 && < 1.10+ Main-Is: BlogLiterately.lhs+ Hs-Source-Dirs: src+ Ghc-Options: -fwarn-unused-imports
+ CHANGES view
@@ -0,0 +1,16 @@+0.4: 2 July 2012++ * Add special support for wordpress.com's LaTeX format++ * Support for [ghci] blocks with contents automatically passed+ through ghci and results typeset++ * Support for tags++ * Support for creating "pages" as well as posts (WordPress only)++ * New standalone documentation++ * Code cleanup++ * Update to build with GHC 7.4.1
LICENSE view
@@ -1,674 +1,674 @@- GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - <program> Copyright (C) <year> <name of author> - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -<http://www.gnu.org/licenses/>. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -<http://www.gnu.org/philosophy/why-not-lgpl.html>. + GNU GENERAL PUBLIC LICENSE+ Version 3, 29 June 2007++ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>+ Everyone is permitted to copy and distribute verbatim copies+ of this license document, but changing it is not allowed.++ Preamble++ The GNU General Public License is a free, copyleft license for+software and other kinds of works.++ The licenses for most software and other practical works are designed+to take away your freedom to share and change the works. By contrast,+the GNU General Public License is intended to guarantee your freedom to+share and change all versions of a program--to make sure it remains free+software for all its users. We, the Free Software Foundation, use the+GNU General Public License for most of our software; it applies also to+any other work released this way by its authors. You can apply it to+your programs, too.++ When we speak of free software, we are referring to freedom, not+price. Our General Public Licenses are designed to make sure that you+have the freedom to distribute copies of free software (and charge for+them if you wish), that you receive source code or can get it if you+want it, that you can change the software or use pieces of it in new+free programs, and that you know you can do these things.++ To protect your rights, we need to prevent others from denying you+these rights or asking you to surrender the rights. Therefore, you have+certain responsibilities if you distribute copies of the software, or if+you modify it: responsibilities to respect the freedom of others.++ For example, if you distribute copies of such a program, whether+gratis or for a fee, you must pass on to the recipients the same+freedoms that you received. You must make sure that they, too, receive+or can get the source code. And you must show them these terms so they+know their rights.++ Developers that use the GNU GPL protect your rights with two steps:+(1) assert copyright on the software, and (2) offer you this License+giving you legal permission to copy, distribute and/or modify it.++ For the developers' and authors' protection, the GPL clearly explains+that there is no warranty for this free software. For both users' and+authors' sake, the GPL requires that modified versions be marked as+changed, so that their problems will not be attributed erroneously to+authors of previous versions.++ Some devices are designed to deny users access to install or run+modified versions of the software inside them, although the manufacturer+can do so. This is fundamentally incompatible with the aim of+protecting users' freedom to change the software. The systematic+pattern of such abuse occurs in the area of products for individuals to+use, which is precisely where it is most unacceptable. Therefore, we+have designed this version of the GPL to prohibit the practice for those+products. If such problems arise substantially in other domains, we+stand ready to extend this provision to those domains in future versions+of the GPL, as needed to protect the freedom of users.++ Finally, every program is threatened constantly by software patents.+States should not allow patents to restrict development and use of+software on general-purpose computers, but in those that do, we wish to+avoid the special danger that patents applied to a free program could+make it effectively proprietary. To prevent this, the GPL assures that+patents cannot be used to render the program non-free.++ The precise terms and conditions for copying, distribution and+modification follow.++ TERMS AND CONDITIONS++ 0. Definitions.++ "This License" refers to version 3 of the GNU General Public License.++ "Copyright" also means copyright-like laws that apply to other kinds of+works, such as semiconductor masks.++ "The Program" refers to any copyrightable work licensed under this+License. Each licensee is addressed as "you". "Licensees" and+"recipients" may be individuals or organizations.++ To "modify" a work means to copy from or adapt all or part of the work+in a fashion requiring copyright permission, other than the making of an+exact copy. The resulting work is called a "modified version" of the+earlier work or a work "based on" the earlier work.++ A "covered work" means either the unmodified Program or a work based+on the Program.++ To "propagate" a work means to do anything with it that, without+permission, would make you directly or secondarily liable for+infringement under applicable copyright law, except executing it on a+computer or modifying a private copy. Propagation includes copying,+distribution (with or without modification), making available to the+public, and in some countries other activities as well.++ To "convey" a work means any kind of propagation that enables other+parties to make or receive copies. Mere interaction with a user through+a computer network, with no transfer of a copy, is not conveying.++ An interactive user interface displays "Appropriate Legal Notices"+to the extent that it includes a convenient and prominently visible+feature that (1) displays an appropriate copyright notice, and (2)+tells the user that there is no warranty for the work (except to the+extent that warranties are provided), that licensees may convey the+work under this License, and how to view a copy of this License. If+the interface presents a list of user commands or options, such as a+menu, a prominent item in the list meets this criterion.++ 1. Source Code.++ The "source code" for a work means the preferred form of the work+for making modifications to it. "Object code" means any non-source+form of a work.++ A "Standard Interface" means an interface that either is an official+standard defined by a recognized standards body, or, in the case of+interfaces specified for a particular programming language, one that+is widely used among developers working in that language.++ The "System Libraries" of an executable work include anything, other+than the work as a whole, that (a) is included in the normal form of+packaging a Major Component, but which is not part of that Major+Component, and (b) serves only to enable use of the work with that+Major Component, or to implement a Standard Interface for which an+implementation is available to the public in source code form. A+"Major Component", in this context, means a major essential component+(kernel, window system, and so on) of the specific operating system+(if any) on which the executable work runs, or a compiler used to+produce the work, or an object code interpreter used to run it.++ The "Corresponding Source" for a work in object code form means all+the source code needed to generate, install, and (for an executable+work) run the object code and to modify the work, including scripts to+control those activities. However, it does not include the work's+System Libraries, or general-purpose tools or generally available free+programs which are used unmodified in performing those activities but+which are not part of the work. For example, Corresponding Source+includes interface definition files associated with source files for+the work, and the source code for shared libraries and dynamically+linked subprograms that the work is specifically designed to require,+such as by intimate data communication or control flow between those+subprograms and other parts of the work.++ The Corresponding Source need not include anything that users+can regenerate automatically from other parts of the Corresponding+Source.++ The Corresponding Source for a work in source code form is that+same work.++ 2. Basic Permissions.++ All rights granted under this License are granted for the term of+copyright on the Program, and are irrevocable provided the stated+conditions are met. This License explicitly affirms your unlimited+permission to run the unmodified Program. The output from running a+covered work is covered by this License only if the output, given its+content, constitutes a covered work. This License acknowledges your+rights of fair use or other equivalent, as provided by copyright law.++ You may make, run and propagate covered works that you do not+convey, without conditions so long as your license otherwise remains+in force. You may convey covered works to others for the sole purpose+of having them make modifications exclusively for you, or provide you+with facilities for running those works, provided that you comply with+the terms of this License in conveying all material for which you do+not control copyright. Those thus making or running the covered works+for you must do so exclusively on your behalf, under your direction+and control, on terms that prohibit them from making any copies of+your copyrighted material outside their relationship with you.++ Conveying under any other circumstances is permitted solely under+the conditions stated below. Sublicensing is not allowed; section 10+makes it unnecessary.++ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.++ No covered work shall be deemed part of an effective technological+measure under any applicable law fulfilling obligations under article+11 of the WIPO copyright treaty adopted on 20 December 1996, or+similar laws prohibiting or restricting circumvention of such+measures.++ When you convey a covered work, you waive any legal power to forbid+circumvention of technological measures to the extent such circumvention+is effected by exercising rights under this License with respect to+the covered work, and you disclaim any intention to limit operation or+modification of the work as a means of enforcing, against the work's+users, your or third parties' legal rights to forbid circumvention of+technological measures.++ 4. Conveying Verbatim Copies.++ You may convey verbatim copies of the Program's source code as you+receive it, in any medium, provided that you conspicuously and+appropriately publish on each copy an appropriate copyright notice;+keep intact all notices stating that this License and any+non-permissive terms added in accord with section 7 apply to the code;+keep intact all notices of the absence of any warranty; and give all+recipients a copy of this License along with the Program.++ You may charge any price or no price for each copy that you convey,+and you may offer support or warranty protection for a fee.++ 5. Conveying Modified Source Versions.++ You may convey a work based on the Program, or the modifications to+produce it from the Program, in the form of source code under the+terms of section 4, provided that you also meet all of these conditions:++ a) The work must carry prominent notices stating that you modified+ it, and giving a relevant date.++ b) The work must carry prominent notices stating that it is+ released under this License and any conditions added under section+ 7. This requirement modifies the requirement in section 4 to+ "keep intact all notices".++ c) You must license the entire work, as a whole, under this+ License to anyone who comes into possession of a copy. This+ License will therefore apply, along with any applicable section 7+ additional terms, to the whole of the work, and all its parts,+ regardless of how they are packaged. This License gives no+ permission to license the work in any other way, but it does not+ invalidate such permission if you have separately received it.++ d) If the work has interactive user interfaces, each must display+ Appropriate Legal Notices; however, if the Program has interactive+ interfaces that do not display Appropriate Legal Notices, your+ work need not make them do so.++ A compilation of a covered work with other separate and independent+works, which are not by their nature extensions of the covered work,+and which are not combined with it such as to form a larger program,+in or on a volume of a storage or distribution medium, is called an+"aggregate" if the compilation and its resulting copyright are not+used to limit the access or legal rights of the compilation's users+beyond what the individual works permit. Inclusion of a covered work+in an aggregate does not cause this License to apply to the other+parts of the aggregate.++ 6. Conveying Non-Source Forms.++ You may convey a covered work in object code form under the terms+of sections 4 and 5, provided that you also convey the+machine-readable Corresponding Source under the terms of this License,+in one of these ways:++ a) Convey the object code in, or embodied in, a physical product+ (including a physical distribution medium), accompanied by the+ Corresponding Source fixed on a durable physical medium+ customarily used for software interchange.++ b) Convey the object code in, or embodied in, a physical product+ (including a physical distribution medium), accompanied by a+ written offer, valid for at least three years and valid for as+ long as you offer spare parts or customer support for that product+ model, to give anyone who possesses the object code either (1) a+ copy of the Corresponding Source for all the software in the+ product that is covered by this License, on a durable physical+ medium customarily used for software interchange, for a price no+ more than your reasonable cost of physically performing this+ conveying of source, or (2) access to copy the+ Corresponding Source from a network server at no charge.++ c) Convey individual copies of the object code with a copy of the+ written offer to provide the Corresponding Source. This+ alternative is allowed only occasionally and noncommercially, and+ only if you received the object code with such an offer, in accord+ with subsection 6b.++ d) Convey the object code by offering access from a designated+ place (gratis or for a charge), and offer equivalent access to the+ Corresponding Source in the same way through the same place at no+ further charge. You need not require recipients to copy the+ Corresponding Source along with the object code. If the place to+ copy the object code is a network server, the Corresponding Source+ may be on a different server (operated by you or a third party)+ that supports equivalent copying facilities, provided you maintain+ clear directions next to the object code saying where to find the+ Corresponding Source. Regardless of what server hosts the+ Corresponding Source, you remain obligated to ensure that it is+ available for as long as needed to satisfy these requirements.++ e) Convey the object code using peer-to-peer transmission, provided+ you inform other peers where the object code and Corresponding+ Source of the work are being offered to the general public at no+ charge under subsection 6d.++ A separable portion of the object code, whose source code is excluded+from the Corresponding Source as a System Library, need not be+included in conveying the object code work.++ A "User Product" is either (1) a "consumer product", which means any+tangible personal property which is normally used for personal, family,+or household purposes, or (2) anything designed or sold for incorporation+into a dwelling. In determining whether a product is a consumer product,+doubtful cases shall be resolved in favor of coverage. For a particular+product received by a particular user, "normally used" refers to a+typical or common use of that class of product, regardless of the status+of the particular user or of the way in which the particular user+actually uses, or expects or is expected to use, the product. A product+is a consumer product regardless of whether the product has substantial+commercial, industrial or non-consumer uses, unless such uses represent+the only significant mode of use of the product.++ "Installation Information" for a User Product means any methods,+procedures, authorization keys, or other information required to install+and execute modified versions of a covered work in that User Product from+a modified version of its Corresponding Source. The information must+suffice to ensure that the continued functioning of the modified object+code is in no case prevented or interfered with solely because+modification has been made.++ If you convey an object code work under this section in, or with, or+specifically for use in, a User Product, and the conveying occurs as+part of a transaction in which the right of possession and use of the+User Product is transferred to the recipient in perpetuity or for a+fixed term (regardless of how the transaction is characterized), the+Corresponding Source conveyed under this section must be accompanied+by the Installation Information. But this requirement does not apply+if neither you nor any third party retains the ability to install+modified object code on the User Product (for example, the work has+been installed in ROM).++ The requirement to provide Installation Information does not include a+requirement to continue to provide support service, warranty, or updates+for a work that has been modified or installed by the recipient, or for+the User Product in which it has been modified or installed. Access to a+network may be denied when the modification itself materially and+adversely affects the operation of the network or violates the rules and+protocols for communication across the network.++ Corresponding Source conveyed, and Installation Information provided,+in accord with this section must be in a format that is publicly+documented (and with an implementation available to the public in+source code form), and must require no special password or key for+unpacking, reading or copying.++ 7. Additional Terms.++ "Additional permissions" are terms that supplement the terms of this+License by making exceptions from one or more of its conditions.+Additional permissions that are applicable to the entire Program shall+be treated as though they were included in this License, to the extent+that they are valid under applicable law. If additional permissions+apply only to part of the Program, that part may be used separately+under those permissions, but the entire Program remains governed by+this License without regard to the additional permissions.++ When you convey a copy of a covered work, you may at your option+remove any additional permissions from that copy, or from any part of+it. (Additional permissions may be written to require their own+removal in certain cases when you modify the work.) You may place+additional permissions on material, added by you to a covered work,+for which you have or can give appropriate copyright permission.++ Notwithstanding any other provision of this License, for material you+add to a covered work, you may (if authorized by the copyright holders of+that material) supplement the terms of this License with terms:++ a) Disclaiming warranty or limiting liability differently from the+ terms of sections 15 and 16 of this License; or++ b) Requiring preservation of specified reasonable legal notices or+ author attributions in that material or in the Appropriate Legal+ Notices displayed by works containing it; or++ c) Prohibiting misrepresentation of the origin of that material, or+ requiring that modified versions of such material be marked in+ reasonable ways as different from the original version; or++ d) Limiting the use for publicity purposes of names of licensors or+ authors of the material; or++ e) Declining to grant rights under trademark law for use of some+ trade names, trademarks, or service marks; or++ f) Requiring indemnification of licensors and authors of that+ material by anyone who conveys the material (or modified versions of+ it) with contractual assumptions of liability to the recipient, for+ any liability that these contractual assumptions directly impose on+ those licensors and authors.++ All other non-permissive additional terms are considered "further+restrictions" within the meaning of section 10. If the Program as you+received it, or any part of it, contains a notice stating that it is+governed by this License along with a term that is a further+restriction, you may remove that term. If a license document contains+a further restriction but permits relicensing or conveying under this+License, you may add to a covered work material governed by the terms+of that license document, provided that the further restriction does+not survive such relicensing or conveying.++ If you add terms to a covered work in accord with this section, you+must place, in the relevant source files, a statement of the+additional terms that apply to those files, or a notice indicating+where to find the applicable terms.++ Additional terms, permissive or non-permissive, may be stated in the+form of a separately written license, or stated as exceptions;+the above requirements apply either way.++ 8. Termination.++ You may not propagate or modify a covered work except as expressly+provided under this License. Any attempt otherwise to propagate or+modify it is void, and will automatically terminate your rights under+this License (including any patent licenses granted under the third+paragraph of section 11).++ However, if you cease all violation of this License, then your+license from a particular copyright holder is reinstated (a)+provisionally, unless and until the copyright holder explicitly and+finally terminates your license, and (b) permanently, if the copyright+holder fails to notify you of the violation by some reasonable means+prior to 60 days after the cessation.++ Moreover, your license from a particular copyright holder is+reinstated permanently if the copyright holder notifies you of the+violation by some reasonable means, this is the first time you have+received notice of violation of this License (for any work) from that+copyright holder, and you cure the violation prior to 30 days after+your receipt of the notice.++ Termination of your rights under this section does not terminate the+licenses of parties who have received copies or rights from you under+this License. If your rights have been terminated and not permanently+reinstated, you do not qualify to receive new licenses for the same+material under section 10.++ 9. Acceptance Not Required for Having Copies.++ You are not required to accept this License in order to receive or+run a copy of the Program. Ancillary propagation of a covered work+occurring solely as a consequence of using peer-to-peer transmission+to receive a copy likewise does not require acceptance. However,+nothing other than this License grants you permission to propagate or+modify any covered work. These actions infringe copyright if you do+not accept this License. Therefore, by modifying or propagating a+covered work, you indicate your acceptance of this License to do so.++ 10. Automatic Licensing of Downstream Recipients.++ Each time you convey a covered work, the recipient automatically+receives a license from the original licensors, to run, modify and+propagate that work, subject to this License. You are not responsible+for enforcing compliance by third parties with this License.++ An "entity transaction" is a transaction transferring control of an+organization, or substantially all assets of one, or subdividing an+organization, or merging organizations. If propagation of a covered+work results from an entity transaction, each party to that+transaction who receives a copy of the work also receives whatever+licenses to the work the party's predecessor in interest had or could+give under the previous paragraph, plus a right to possession of the+Corresponding Source of the work from the predecessor in interest, if+the predecessor has it or can get it with reasonable efforts.++ You may not impose any further restrictions on the exercise of the+rights granted or affirmed under this License. For example, you may+not impose a license fee, royalty, or other charge for exercise of+rights granted under this License, and you may not initiate litigation+(including a cross-claim or counterclaim in a lawsuit) alleging that+any patent claim is infringed by making, using, selling, offering for+sale, or importing the Program or any portion of it.++ 11. Patents.++ A "contributor" is a copyright holder who authorizes use under this+License of the Program or a work on which the Program is based. The+work thus licensed is called the contributor's "contributor version".++ A contributor's "essential patent claims" are all patent claims+owned or controlled by the contributor, whether already acquired or+hereafter acquired, that would be infringed by some manner, permitted+by this License, of making, using, or selling its contributor version,+but do not include claims that would be infringed only as a+consequence of further modification of the contributor version. For+purposes of this definition, "control" includes the right to grant+patent sublicenses in a manner consistent with the requirements of+this License.++ Each contributor grants you a non-exclusive, worldwide, royalty-free+patent license under the contributor's essential patent claims, to+make, use, sell, offer for sale, import and otherwise run, modify and+propagate the contents of its contributor version.++ In the following three paragraphs, a "patent license" is any express+agreement or commitment, however denominated, not to enforce a patent+(such as an express permission to practice a patent or covenant not to+sue for patent infringement). To "grant" such a patent license to a+party means to make such an agreement or commitment not to enforce a+patent against the party.++ If you convey a covered work, knowingly relying on a patent license,+and the Corresponding Source of the work is not available for anyone+to copy, free of charge and under the terms of this License, through a+publicly available network server or other readily accessible means,+then you must either (1) cause the Corresponding Source to be so+available, or (2) arrange to deprive yourself of the benefit of the+patent license for this particular work, or (3) arrange, in a manner+consistent with the requirements of this License, to extend the patent+license to downstream recipients. "Knowingly relying" means you have+actual knowledge that, but for the patent license, your conveying the+covered work in a country, or your recipient's use of the covered work+in a country, would infringe one or more identifiable patents in that+country that you have reason to believe are valid.++ If, pursuant to or in connection with a single transaction or+arrangement, you convey, or propagate by procuring conveyance of, a+covered work, and grant a patent license to some of the parties+receiving the covered work authorizing them to use, propagate, modify+or convey a specific copy of the covered work, then the patent license+you grant is automatically extended to all recipients of the covered+work and works based on it.++ A patent license is "discriminatory" if it does not include within+the scope of its coverage, prohibits the exercise of, or is+conditioned on the non-exercise of one or more of the rights that are+specifically granted under this License. You may not convey a covered+work if you are a party to an arrangement with a third party that is+in the business of distributing software, under which you make payment+to the third party based on the extent of your activity of conveying+the work, and under which the third party grants, to any of the+parties who would receive the covered work from you, a discriminatory+patent license (a) in connection with copies of the covered work+conveyed by you (or copies made from those copies), or (b) primarily+for and in connection with specific products or compilations that+contain the covered work, unless you entered into that arrangement,+or that patent license was granted, prior to 28 March 2007.++ Nothing in this License shall be construed as excluding or limiting+any implied license or other defenses to infringement that may+otherwise be available to you under applicable patent law.++ 12. No Surrender of Others' Freedom.++ If conditions are imposed on you (whether by court order, agreement or+otherwise) that contradict the conditions of this License, they do not+excuse you from the conditions of this License. If you cannot convey a+covered work so as to satisfy simultaneously your obligations under this+License and any other pertinent obligations, then as a consequence you may+not convey it at all. For example, if you agree to terms that obligate you+to collect a royalty for further conveying from those to whom you convey+the Program, the only way you could satisfy both those terms and this+License would be to refrain entirely from conveying the Program.++ 13. Use with the GNU Affero General Public License.++ Notwithstanding any other provision of this License, you have+permission to link or combine any covered work with a work licensed+under version 3 of the GNU Affero General Public License into a single+combined work, and to convey the resulting work. The terms of this+License will continue to apply to the part which is the covered work,+but the special requirements of the GNU Affero General Public License,+section 13, concerning interaction through a network will apply to the+combination as such.++ 14. Revised Versions of this License.++ The Free Software Foundation may publish revised and/or new versions of+the GNU General Public License from time to time. Such new versions will+be similar in spirit to the present version, but may differ in detail to+address new problems or concerns.++ Each version is given a distinguishing version number. If the+Program specifies that a certain numbered version of the GNU General+Public License "or any later version" applies to it, you have the+option of following the terms and conditions either of that numbered+version or of any later version published by the Free Software+Foundation. If the Program does not specify a version number of the+GNU General Public License, you may choose any version ever published+by the Free Software Foundation.++ If the Program specifies that a proxy can decide which future+versions of the GNU General Public License can be used, that proxy's+public statement of acceptance of a version permanently authorizes you+to choose that version for the Program.++ Later license versions may give you additional or different+permissions. However, no additional obligations are imposed on any+author or copyright holder as a result of your choosing to follow a+later version.++ 15. Disclaimer of Warranty.++ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.++ 16. Limitation of Liability.++ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF+SUCH DAMAGES.++ 17. Interpretation of Sections 15 and 16.++ If the disclaimer of warranty and limitation of liability provided+above cannot be given local legal effect according to their terms,+reviewing courts shall apply local law that most closely approximates+an absolute waiver of all civil liability in connection with the+Program, unless a warranty or assumption of liability accompanies a+copy of the Program in return for a fee.++ END OF TERMS AND CONDITIONS++ How to Apply These Terms to Your New Programs++ If you develop a new program, and you want it to be of the greatest+possible use to the public, the best way to achieve this is to make it+free software which everyone can redistribute and change under these terms.++ To do so, attach the following notices to the program. It is safest+to attach them to the start of each source file to most effectively+state the exclusion of warranty; and each file should have at least+the "copyright" line and a pointer to where the full notice is found.++ <one line to give the program's name and a brief idea of what it does.>+ Copyright (C) <year> <name of author>++ This program is free software: you can redistribute it and/or modify+ it under the terms of the GNU General Public License as published by+ the Free Software Foundation, either version 3 of the License, or+ (at your option) any later version.++ This program is distributed in the hope that it will be useful,+ but WITHOUT ANY WARRANTY; without even the implied warranty of+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+ GNU General Public License for more details.++ You should have received a copy of the GNU General Public License+ along with this program. If not, see <http://www.gnu.org/licenses/>.++Also add information on how to contact you by electronic and paper mail.++ If the program does terminal interaction, make it output a short+notice like this when it starts in an interactive mode:++ <program> Copyright (C) <year> <name of author>+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.+ This is free software, and you are welcome to redistribute it+ under certain conditions; type `show c' for details.++The hypothetical commands `show w' and `show c' should show the appropriate+parts of the General Public License. Of course, your program's commands+might be different; for a GUI interface, you would use an "about box".++ You should also get your employer (if you work as a programmer) or school,+if any, to sign a "copyright disclaimer" for the program, if necessary.+For more information on this, and how to apply and follow the GNU GPL, see+<http://www.gnu.org/licenses/>.++ The GNU General Public License does not permit incorporating your program+into proprietary programs. If your program is a subroutine library, you+may consider it more useful to permit linking proprietary applications with+the library. If this is what you want to do, use the GNU Lesser General+Public License instead of this License. But first, please read+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
Setup.hs view
@@ -1,4 +1,4 @@-import Distribution.Simple - -main = defaultMain - +import Distribution.Simple++main = defaultMain+
+ doc/BlogLiteratelyDoc.lhs view
@@ -0,0 +1,258 @@+[`BlogLiterately`][] is a tool for uploading blog posts to servers that+support the [MetaWeblog API][metaweblog] (such as [WordPress][]-based+blogs and many others). Blog posts to be published via+`BlogLiterately` are written in [markdown][] format, with extensions+supported by [pandoc][]. Posts may be actual "bird-style" literate+Haskell files, with commentary in markdown. Though `BlogLiterately`+offers special support for literate Haskell in particular, it is also+useful for writing posts including code written in other languages, or+even no code at all.++`BlogLiterately` includes support for syntax highlighting, $\LaTeX$+(including special support for WordPress blogs), and automatic+generation and formatting of `ghci` sessions. Each of these features+is explained in more detail below.++Markdown and pandoc+-------------------++`BlogLiterately` takes as input files written using the [markdown][]+format. See the [markdown website][markdown] for detailed+documentation. `BlogLiterately` uses [pandoc][] for reading markdown,+which also [supports a few+extensions](http://johnmacfarlane.net/pandoc/README.html#pandocs-markdown)+to the basic format.++Code blocks and syntax highlighting+-----------------------------------++Code segments (including actual source lines from literate haskell+files, as well as markdown code blocks) may be syntax highlighted.+Two different syntax highlighting libraries are supported:++ * [hscolour][] is specifically for syntax highlighting of Haskell+ code, and is the standard highlighter used on [Hackage][] and+ elsewhere.+ * [highlighting-kate][] is a general syntax highlighting library+ that can be used for highlighting a wide range of languages+ (including Haskell).++You may independently specify whether to use `hscolour` or+`highlighting-kate` to highlight Haskell code; other languages will be+highlighted with `highlighting-kate`.++In basic markdown, a generic code block is set off from normal text+by indenting at least four spaces:++ -- This is a code segment, but what language is it?+ foo :: String -> String++However, markdown has no way of specifying the language used in a code+block, making support for syntax highlighting problematic. Pandoc+offers [an alternative+syntax](http://johnmacfarlane.net/pandoc/README.html#pandocs-markdown)+for code segments which does allow specifying the language:++ ~~~~ { .haskell }+ -- This is a Haskell code segment!+ foo :: String -> String+ ~~~~++`BlogLiterately` also supports one additional style, consisting of a+normal markdown indented code block with an extra tag at the top,+enclosed in square brackets:++ [haskell]+ -- This is also a Haskell code segment!+ foo :: String -> String++Of course, languages other than Haskell may be specified as well.++By default, `hscolour` will be used for highlighting Haskell code,+using "inline" CSS style attributes. The default styling is similar+to that used for source code in documentation on [Hackage][]. You can+also specify a configuration file containing a Haskell value of type+[(String,String)] which specifies a CSS style for each syntax+class. An example (corresponding to the default configuration) is+provided in the package archive (`hs-style`).++With `highlighting-kate`, the style for syntax segments is specified+using "class" attributes, so the stylesheet must be provided+separately. You may optionally use a similar scheme with `hscolour`.+Sample stylesheets are provided in the package archive file+(`kate.css`, `hscolour.css`).++LaTeX+-----++LaTeX can be included in documents using single dollar signs to+enclose inline LaTeX, and double dollar signs to enclose+"display-style" LaTeX. For example, `$\pi^2 / 6$` produces $\pi^2 /+6$, and `$$\sum_{k=0}^\infty 1/k^2$$` (when put by itself in its own+paragraph) produces++$$\sum_{k=0}^\infty 1/k^2.$$++By default, LaTeX is processed with Pandoc, meaning that a+certain subset of LaTeX expressions (such as those above) will be+transformed into [MathML][], and anything Pandoc cannot parse will be+passed through as literal LaTeX enclosed in dollar signs.++Blogs hosted on [wordpress.com](http://www.wordpress.com), however,+have built-in support for LaTeX, compiling LaTeX expressions to+embedded images on-the-fly. Passing the `--wplatex` option to+`BlogLiterately` causes any embedded LaTeX to be output in the format+expected by WordPress. Note that an extra `$latex...` won't be added+to the beginning of LaTeX expressions which already appear to be in+WordPress format.++When working with other blogging platforms that do not directly+support LaTeX, it might be nice for `BlogLiterately` to have some sort+of [MathJax][] support. This is future work; drop a note (or a+patch!) if you would like to see this added.++`ghci` sessions+---------------++When writing literate Haskell documents, it is often useful to show a+sample `ghci` session illustrating the behavior of the code being+described. However, manually pasting in the results of sample+sessions is tedious and error-prone, and it can be difficult keeping+sample sessions "in sync" when making changes to the code.++For these reasons, `BlogLiterately` supports special `[ghci]` code+blocks, consisting of a list of Haskell expressions (or, more+generally, arbitrary `ghci` commands), one per line. These+expressions/commands are evaluated using `ghci`, and the results+typeset along with the original expressions in the output document.+The entire literate Haskell document itself will be loaded into `ghci`+before evaluating the expressions, so expressions may reference+anything in scope. Note also that all expressions in the entire+document will be evaluated in the *same* `ghci` session, so names+bound with `let` or `<-` will also be in scope in subsequent+expressions, even across multiple `[ghci]` blocks.++For example, consider the following definition:++> hailstone x+> | even x = x `div` 2+> | otherwise = 3*x + 1++Now, given the input++ [other]+ [ghci]+ :t hailstone+ hailstone 15+ takeWhile (/= 1) . iterate hailstone $ 7+ txt <- readFile "BlogLiteratelyDoc.lhs"+ length txt++`BlogLiterately` will generate the following output:++ [ghci]+ :t hailstone+ hailstone 15+ takeWhile (/= 1) . iterate hailstone $ 7+ txt <- readFile "BlogLiteratelyDoc.lhs"+ length txt++There are currently a few known limitations of this feature:++* The code for interfacing with `ghci` is not very robust. In+ particular, expressions which generate an error (*e.g.* ones which+ refer to an out-of-scope name, or do not typecheck) will simply lack+ any accompanying output; it would be much more useful to display the+ accompanying error message.++* If the literate document itself fails to load (*e.g.* due to+ improper formatting) `BlogLiterately` may hang.++* The formatting of `ghci` sessions currently cannot be+ customized. Suggestions for customizations to allow are welcome.++Uploading embedded images+-------------------------++A planned feature for a future release of `BlogLiterately` is the+ability to automatically upload images embedded in a blog post to the+server, replacing local image file names with the appropriate URL.+However, this feature is currently [blocked on a baffling+bug](http://stackoverflow.com/questions/11277788/errorclosed-exception-from-network-http-simplehttp-trying-to-upload-images-vi).+If you know anything about HTTP, TCP/IP, XML-RPC, WordPress, and/or+the `HTTP` and `haxr` libraries, please help!++Command-line options+--------------------++The options for `BlogLiterately` are hopefully self-explanatory, given the+above background:++ BlogLierately v0.4, (c) Robert Greayer 2008-2010, Brent Yorgey 2012+ This program comes with ABSOLUTELY NO WARRANTY++ BlogLiterately [OPTIONS] FILE++ Common flags:+ -s --style=FILE style specification (for --hscolour-icss)+ --hscolour-icss highlight haskell: hscolour, inline style (default)+ --hscolour-css highlight haskell: hscolour, separate stylesheet+ --hs-nohighlight no haskell highlighting+ --hs-kate highlight haskell with highlighting-kate+ --other-kate highlight other code with highlighting-kate+ -w --wplatex reformat inline LaTeX the way WordPress expects+ -g --ghci run [ghci] blocks through ghci and include output+ --category=ITEM post category (can specify more than one)+ --tag=ITEM tag (can specify more than one)+ --blogid=ID Blog specific identifier+ --blog=URL blog XML-RPC url (if omitted, html goes to stdout)+ -u --user=USER user name+ --password=PASSWORD password+ -t --title=TITLE post title+ --postid=ID Post to replace (if any)+ --page create a "page" instead of a post (WordPress only)+ --publish publish post (otherwise it's uploaded as a draft)+ -? --help Display help message+ -V --version Print version information++Example usage+-------------++If you do not specify a blog URL, by default `BlogLiterately` simply+prints the generated HTML to stdout. So, to preview the generated+HTML before uploading requires merely something like++ BlogLiterately Sample.lhs++To actually post to, say, a WordPress blog, a basic command line would+be something like++ BlogLiterately --blog http://blogurl.example.com/xmlrpc.php \+ --user myname --password mypasswd --title "Sample" Sample.lhs++(which creates a new post). If, for example, the post id of that post+(which `BlogLiterately` prints when it uploads a new post) is '37', then+to update the post, the command would be:++ BlogLiterately --postid 37 --blog http://blogurl.example.com/xmlrpc.php \+ --user myname --password mypasswd --title "Sample" Sample.lhs++and the post will be updated with the new text.++Getting Help+------------++For questions, support, feature suggestions, etc., feel free to+contact me (Brent Yorgey): `byorgey` on IRC (freenode), or `byorgey`+at gmail.++[`BlogLiterately`]: http://hackage.haskell.org/package/BlogLiterately+[markdown]: http://daringfireball.net/projects/markdown/+[pandoc]: http://johnmacfarlane.net/pandoc/+[hscolour]: http://www.cs.york.ac.uk/fp/darcs/hscolour/+[highlighting-kate]: http://johnmacfarlane.net/highlighting-kate/+[metaweblog]: http://www.xmlrpc.com/metaWeblogApi+[WordPress]: http://wordpress.org/+[Hackage]: http://hackage.haskell.org/+[MathML]: http://www.w3.org/Math/+[MathJax]: http://www.mathjax.org/
− hscolour.css
@@ -1,6 +0,0 @@-.hs-keyglyph, .hs-layout {color: red;} -.hs-keyword {color: blue;} -.hs-comment, .hs-comment a {color: green;} -.hs-str, .hs-chr {color: teal;} -.hs-keyword,.hs-conid, .hs-varid, .hs-conop, .hs-varop {} -.hs-num, .hs-cpp, .hs-sel, .hs-definition {}
− kate.css
@@ -1,23 +0,0 @@-/* this file was derived from highlighting-kate which is Copyright - John MacFarlane. Approximately the same file, along with other - stylesheets, are available in the highlighting-kate package on - hackage. */ -table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode, table.sourceCode pre - { margin: 0; padding: 0; border: 0; vertical-align: baseline; border: none; } -td.lineNumbers { border-right: 1px solid #AAAAAA; text-align: right; color: #AAAAAA; padding-right: 5px; padding-left: 5px; } -td.sourceCode { padding-left: 5px; } -pre.sourceCode { } -pre.sourceCode span.Normal { } -pre.sourceCode span.Keyword { color: #007020; font-weight: bold; } -pre.sourceCode span.DataType { color: #902000; } -pre.sourceCode span.DecVal { color: #40a070; } -pre.sourceCode span.BaseN { color: #40a070; } -pre.sourceCode span.Float { color: #40a070; } -pre.sourceCode span.Char { color: #4070a0; } -pre.sourceCode span.String { color: #4070a0; } -pre.sourceCode span.Comment { color: #60a0b0; font-style: italic; } -pre.sourceCode span.Others { color: #007020; } -pre.sourceCode span.Alert { color: red; font-weight: bold; } -pre.sourceCode span.Function { color: #06287e; } -pre.sourceCode span.RegionMarker { } -pre.sourceCode span.Error { color: red; font-weight: bold; }
src/BlogLiterately.lhs view
@@ -1,473 +1,668 @@-This new version of BlogLiterately adds a few more options and tries to allow -the user to take advantage of the Pandoc syntax highlighting, or suppress -it. - -> {-# LANGUAGE DeriveDataTypeable #-} -> module Main where - -We need [Pandoc][] for parsing [Markdown][]: - -> import Text.Pandoc -> import Text.Pandoc.Highlighting - -And [hscolour][] for highlighting: - -> import Language.Haskell.HsColour(hscolour,Output(..)) -> import Language.Haskell.HsColour.Colourise(defaultColourPrefs) - -To post to a blog, we need the [MetaWeblog][] API, which is an XML-RPC-based -protocol for interacting with blogs. - -We'll use the Haskell XML-RPC library, [HaXR][], by Bjorn Bringert, (on -[hackage][hackage-haxr]). *Note: the latest version (as of this writing) of -HaXR on Hackage does not specify an upper bound in its dependency on HaXml, but -it is incompatible with the 1.19 versions of HaXml! If you have HaXml-1.19.* -installed, you'll have to work around this.* - -> import Network.XmlRpc.Client -> import Network.XmlRpc.Internals - -And it works that out I'll need some miscellaneous other stuff. Since I'm -writing a command line tool, I'll need to process the command line arguments, -and Neil Mitchell's [CmdArgs][] library ought to work for that: - -> import System.Console.CmdArgs - -I'm going to end up needing to parse and manipulate XHTML, so I'll use Malcolm -Wallace's [HaXml][] XML combinators: - -> import Text.XML.HaXml -> import Text.XML.HaXml.Posn -> import Text.XML.HaXml.Verbatim - -> import qualified System.IO.UTF8 as U - -> import Control.Monad(liftM,unless) -> import Text.XHtml.Transitional(showHtmlFragment) -> import Text.ParserCombinators.Parsec - -The program will read in a literate Haskell file, use Pandoc to parse it as -markdown, and, if it is using hscolour to for the Haskell pieces, will use -hscolour to transform those. Pandoc turns its input into a structure of type: - - [haskell] - data Pandoc = Pandoc Meta [Block] - -where a `Block` (the interesting bit, for my purposes) looks like: - - [haskell] - -- | Block element. - data Block - = Plain [Inline] -- ^ Plain text, not a paragraph - | Para [Inline] -- ^ Paragraph - | CodeBlock Attr String -- ^ Code block (literal) with attributes - | RawHtml String -- ^ Raw HTML block (literal) - | BlockQuote [Block] -- ^ Block quote (list of blocks) - | OrderedList ListAttributes [[Block]] -- ^ Ordered list (attributes - -- and a list of items, each a list of blocks) - | BulletList [[Block]] -- ^ Bullet list (list of items, each - -- a list of blocks) - | DefinitionList [([Inline],[Block])] -- ^ Definition list - -- (list of items, each a pair of an inline list, - -- the term, and a block list) - | Header Int [Inline] -- ^ Header - level (integer) and text (inlines) - | HorizontalRule -- ^ Horizontal rule - | Table [Inline] [Alignment] [Double] [[Block]] [[[Block]]] -- ^ Table, - -- with caption, column alignments, - -- relative column widths, column headers - -- (each a list of blocks), and rows - -- (each a list of lists of blocks) - | Null -- ^ Nothing - deriving (Eq, Read, Show, Typeable, Data) - -The literate Haskell that Pandoc finds in a file ends up in various `CodeBlock` -elements of the `Pandoc` document. Other code can also wind up in `CodeBlock` -elements -- normal markdown formatted code. The `Attr` component has -metadata about what's in the code block: - - [haskell] - type Attr = (String, -- code block identifier - [String], -- list of code classes - [(String, String)]) -- name/value pairs - -Thanks to some feedback from the Pandoc author, John MacFarlane, I learned that -the CodeBlock *may* contain markers about the kind of code contained within the -block. LHS (bird-style or LaTex style) will always have an `Attr` of the form -`("",["sourceCode","haskell"],[])`, and other `CodeBlock` -elements are the markdown code blocks *may* have an identifier, classes, or -key/value pairs. Pandoc captures this info when the file contains code blocks -in the delimited (rather than indented) format, which allows an optional -meta-data specification, e.g. - -~~~~~~~~~~~ -~~~~~~~ { .bash } -x=$1 -echo $x -~~~~~~~ -~~~~~~~~~~~ - -Although Pandoc supports the above format for marking code blocks (and -annotating the kind of code within the block) I'll also keep my notation as -another option for use with indented blocks, i.e. if you write: - -<pre><code> - [haskell] - foo :: String -> String -</code></pre> - -it is a Haskell block. If it looks like something else, e.g. - -<pre><code> - [cpp] - cout << "Hello World!"; -</code></pre> - -or -<pre><code> - [other] - foo bar baz -</pre></code> - -If highlighting-kate is specified for highlighting Haskell blocks, the distinction -between the literate blocks and the delimited blocks is lost (this is simply how -the Pandoc highlighting module currently works). - -I'll adopt the rule that if you specify a class or -classes using Pandoc's delimited code block syntax, I'll assume that there is -no additional tag within the block in Blog Literately syntax. I still need my -`unTag` function to parse the code block. - -> unTag :: String -> (String, String) -> unTag s = either (const ("",s)) id $ parse tag "" s -> where tag = do -> tg <- between (char '[') (char ']') $ many $ noneOf "[]" -> skipMany $ oneOf " \t" -> (string "\r\n" <|> string "\n") -> txt <- many $ anyToken -> eof -> return (tg,txt) - -To highlight the syntax using hscolour (which produces HTML), I'm going to -need to transform the `String` from a `CodeBlock` element to a `String` -suitable for the `RawHtml` element (because the hscolour library transforms -Haskell text to HTML). Pandoc strips off the prepended > characters from the -literate Haskell, so I need to put them back, and also tell hscolour whether the -source it is colouring is literate or not. The hscolour function looks like: - - [haskell] - hscolour :: Output -- ^ Output format. - -> ColourPrefs -- ^ Colour preferences... - -> Bool -- ^ Whether to include anchors. - -> Bool -- ^ Whether output document is partial or complete. - -> String -- ^ Title for output. - -> Bool -- ^ Whether input document is literate haskell - -> String -- ^ Haskell source code. - -> String -- ^ Coloured Haskell source code. - -Since I still don't like the `ICSS` output from hscolour, I'm going to provide -two options for hscolouring to users: one that simply uses hscolour's `CSS` -format, so the user can provide definitions in their blog's stylesheet to -control the rendering, and a post-processing option to transform the `CSS` -class-based rendering into a inline style based rendering (for people who can't -update their stylesheet). `colourIt` performs the initial transformation: - -> colourIt literate srcTxt = -> hscolour CSS defaultColourPrefs False True "" literate srcTxt' -> where srcTxt' | literate = prepend srcTxt -> | otherwise = srcTxt - -Prepending the literate Haskell markers on the source: - -> prepend s = unlines $ map ("> " ++) $ lines s - -Hscolour uses HTML `span` elements and CSS classes like 'hs-keyword' or -`hs-keyglyph` to markup Haskell code. What I want to do is take each marked -`span` element and replace the `class` attribute with an inline `style` element -that has the markup I want for that kind of source. I've rethought the style -preferences type, and think it will be simpler, and more general, as just a list -of name/value pairs: - -> type StylePrefs = [(String,String)] - -The default style that produces something like what the source listings -on Hackage look like is now: - -> defaultStylePrefs = [ -> ("hs-keyword","color: blue; font-weight: bold;") -> , ("hs-keyglyph","color: red;") -> , ("hs-layout","color: red;") -> , ("hs-comment","color: green;") -> , ("hs-conid", "") -> , ("hs-varid", "") -> , ("hs-conop", "") -> , ("hs-varop", "") -> , ("hs-str", "color: teal;") -> , ("hs-chr", "color: teal;") -> , ("hs-number", "") -> , ("hs-cpp", "") -> , ("hs-selection", "") -> , ("hs-variantselection", "") -> , ("hs-definition", "")] - -I can read these preferences in from a file using the `Read` instance for -`StylePrefs`. I could handle errors better, but this should work: - -> getStylePrefs "" = return defaultStylePrefs -> getStylePrefs fname = liftM read (U.readFile fname) - -Hscolour produces a `String` of HTML. To 'bake' the styles into -the HTML it, we need to parse it, manipulate it -and then re-render it as a `String`. Use HaXml to do all of this: - -> bakeStyles :: StylePrefs -> String -> String -> bakeStyles prefs s = verbatim $ filtDoc (xmlParse "bake-input" s) where -> -- filter the document (an Hscoloured fragment of Haskell source) -> filtDoc (Document p s e m) = c where -> [c] = filts (CElem e noPos) -> -- the filter is a fold of individual filters for each CSS class -> filts = mkElem "pre" [(foldXml $ foldl o keep $ map filt prefs) `o` replaceTag "code"] -> -- an individual filter replaces the attributes of a tag with -> -- a style attribute when it has a specific 'class' attribute. -> filt (cls,style) = -> replaceAttrs [("style",style)] `when` -> (attrval $ ("class",AttValue [Left cls])) - -Highlighting-Kate uses <br/> in code blocks to indicate newlines. WordPress -(if not other software) chooses to strip them away when found in <pre> sections -of uploaded HTML. So need to turn them back to newlines. - -> replaceBreaks :: String -> String -> replaceBreaks s = verbatim $ filtDoc (xmlParse "input" s) where -> -- filter the document (a highlighting-kate hitlited fragment of -> -- haskell source -> filtDoc (Document p s e m) = c where -> [c] = filts (CElem e noPos) -> filts = foldXml (literal "\n" `when` tag "br") - -Note to self: the above is a function that could be made better in a -few ways and then factored out into a library. A way to handle the -above would be to allow the preferences to be specified as an actual CSS -style sheet, which then would be baked into the HTML. Such a function -could be separately useful, and could be used to 'bake' in the -highlighting-kate styles. - -To completely colourise/highlight a `CodeBlock` we now can create a function -that transforms a `CodeBlock` into a `RawHtml` block, where the content contains -marked up Haskell (possibly with literate markers), or marked up non-Haskell, if -highlighting of non-Haskell has been selected. - -> colouriseCodeBlock :: HsHighlight -> Bool -> Block -> Block -> colouriseCodeBlock hsHilite otherHilite b@(CodeBlock attr@(_,classes,_) s) = -> if tag == "haskell" || haskell -> then case hsHilite of -> HsColourInline style -> -> RawHtml $ bakeStyles style $ colourIt lit src -> HsColourCSS -> RawHtml $ colourIt lit src -> HsNoHighlight -> RawHtml $ simpleHTML hsrc -> HsKate -> if null tag -> then myHiliteK attr hsrc -> else myHiliteK ("",tag:classes,[]) hsrc -> else if otherHilite -> then case tag of -> "" -> myHiliteK attr src -> t -> myHiliteK ("",[t],[]) src -> else RawHtml $ simpleHTML src -> where (tag,src) = if null classes then unTag s else ("",s) -> hsrc = if lit then prepend src else src -> lit = "sourceCode" `elem` classes -> haskell = "haskell" `elem` classes -> simpleHTML s = "<pre><code>" ++ s ++ "</code></pre>" -> myHiliteK attr s = case highlightHtml attr s of -> Left _ -> RawHtml $ simpleHTML s -> Right html -> RawHtml $ replaceBreaks $ showHtmlFragment html -> colouriseCodeBlock _ _ b = b - -Colourising a `Pandoc` document is simply: - -> colourisePandoc hsHilite otherHilite (Pandoc m blocks) = -> Pandoc m $ map (colouriseCodeBlock hsHilite otherHilite) blocks - -Transforming a complete input document string to an HTML output string: - -> xformDoc :: HsHighlight -> Bool -> String -> String -> xformDoc hsHilite otherHilite s = -> showHtmlFragment -> $ writeHtml writeOpts -- from Pandoc -> $ colourisePandoc hsHilite otherHilite -> $ readMarkdown parseOpts -- from Pandoc -> $ fixLineEndings s -> where writeOpts = defaultWriterOptions { -> --writerLiterateHaskell = True, -> writerReferenceLinks = True } -> parseOpts = defaultParserState { -> stateLiterateHaskell = True } -> -- readMarkdown is picky about line endings -> fixLineEndings [] = [] -> fixLineEndings ('\r':'\n':cs) = '\n':fixLineEndings cs -> fixLineEndings (c:cs) = c:fixLineEndings cs - - -The metaWeblog API defines a `newPost` and `editPost` procedures that look -like: - - [other] - metaWeblog.newPost (blogid, username, password, struct, publish) - returns string - metaWeblog.editPost (postid, username, password, struct, publish) - returns true - -For my blog (a WordPress blog), the `blogid` is just `default`. The user -name and password are simply strings, and `publish` is a flag indicating whether -to load the post as a draft, or to make it public immediately. The `postid` is -an identifier string which is assigned when you initially create a post. The -interesting bit is the `struct` field, which is an XML-RPC structure defining -the post along with some meta-data, like the title. I want be able to provide -the post body, a title, and a list of categories. The for the -body and title, we could just let HaXR convert the values automatically -into the XML-RPC `Value` type, since they all have the same Haskell type -(`String`) and thus can be put into a list. But the categories are a list of -strings, so we need to explicitly convert everything to a `Value`, then combine: - -> mkPost title text categories = -> cats ++ [("title",toValue title),("description",toValue text)] -> where cats = if null categories then [] -> else [("categories",toValue categories)] - -The HaXR library exports a function for invoking XML-RPC procedures: - - [haskell] - remote :: Remote a => - String -- ^ Server URL. May contain username and password on - -- the format username:password\@ before the hostname. - -> String -- ^ Remote method name. - -> a -- ^ Any function - -- @(XmlRpcType t1, ..., XmlRpcType tn, XmlRpcType r) => - -- t1 -> ... -> tn -> IO r@ - -The function requires an URL and a method name, and returns a function of type -`Remote a => a`. Based on the instances defined for `Remote`, any function -with zero or more parameters in the class `XmlRpcType` and a return type of -`XmlRpcType r => IO r` will work, which means you can simply 'feed' `remote` -additional arguments as required by the remote procedure, and as long as you -make the call in an IO context, it will typecheck. So to call the -`metaWeblog.newPost` procedure, I can do something like: - -> postIt :: String -> String -> String -> String -> String -> String -> -> [String] -> Bool -> IO String -> postIt url blogId user password title text cats publish = -> remote url "metaWeblog.newPost" blogId user password -> (mkPost title text cats) publish - -To update (replace) a post, the function would be: - -> updateIt :: String -> String -> String -> String -> String -> String -> -> [String] -> Bool -> IO Bool -> updateIt url postId user password title text cats publish = -> remote url "metaWeblog.editPost" postId user password -> (mkPost title text cats) publish - -There are four modes of Haskell highlighting: - -> data HsHighlight = HsColourInline { hsStylePrefs :: StylePrefs } -> | HsColourCSS | HsKate | HsNoHighlight -> deriving (Data,Typeable,Show,Eq) - -And two modes for other code (off or on!). - -We can figure out if Pandoc is linked with highlighting-kate (we -won't show the kate-related options if it isn't): - -> noKate = null defaultHighlightingCss - -To create a command line program, I can capture the command line controls in a type: - -> data BlogLiterately = BlogLiterately { -> test :: Bool, -- do a dry-run: html goes to stdout -> style :: String, -- name of a style file -> hshighlight :: HsHighlight, -> highlightOther :: Bool, -- use highlight-kate to highlight other code -> publish :: Bool, -- an indication of whether the post should be -> -- published, or loaded as a draft -> categories :: [String], -- -> blogid :: String, -- blog-specific identifier (e.g. for blogging -> -- software handling multiple blogs) -> blog :: String, -- blog xmlrpc URL -> user :: String, -- blog user name -> password :: String, -- blog password -> title :: String, -- post title -> file :: String, -- file to post -> postid :: String -- id of a post to updated -> } deriving (Show,Data,Typeable) - -And using CmdArgs, this bit of impure evil defines how the command line arguments -work: - -> bl = mode $ BlogLiterately { -> test = def &= text "do a test-run: html goes to stdout, is not posted", -> style = "" &= text "Style Specification (for --hscolour-icss)" & typFile, -> hshighlight = enum (HsColourInline defaultStylePrefs) -> ([ (HsColourInline defaultStylePrefs) &= explicit & -> flag "hscolour-icss" & text inline, -> HsColourCSS &= explicit & flag "hscolour-css" & text css, -> HsNoHighlight &= explicit & flag "hs-nohilight" & -> text "no haskell hilighting" ] ++ -> (if noKate then [] else -> [HsKate &= explicit & flag "hs-kate" & text hskate])), -> highlightOther = enum False -> (if noKate then [] else -> [True &= explicit & flag "other-code-kate" & -> text "hilight other code with highlighting-kate"]), -> publish = def &= text "Publish post (otherwise it's uploaded as a draft)", -> categories = def &= explicit & flag "category" & -> text "post category (can specify more than one)", -> blogid = "default" &= text "Blog specific identifier", -> blog = def &= argPos 0 & typ "URL" -> & text "URL of blog's xmlrpc address (e.g. http://example.com/blog/xmlrpc.php)", -> user = def &= argPos 1 & typ "USER" & text "blog author's user name" , -> password = def &= argPos 2 & typ "PASSWORD" & text "blog author's password", -> title = def &= argPos 3 & typ "TITLE", -> file = def &= argPos 4 & typ "FILE" & text "literate haskell file", -> postid = "" &= text "Post to replace (if any)" } where -> inline = "hilight haskell: hscolour, inline style (default)" -> css = "hilight haskell: hscolour, separate stylesheet" -> hskate = "hilight haskell with highlighting-kate" - -The main blogging function uses the information captured in the `BlogLiterately` -type to read the style preferences, read the input file and transform it, and -post it to the blog: - -> blogLiterately (BlogLiterately test style hsmode other pub cats blogid url -> user pw title file postid) = do -> prefs <- getStylePrefs style -> let hsmode' = case hsmode of -> HsColourInline _ -> HsColourInline prefs -> _ -> hsmode -> html <- liftM (xformDoc hsmode' other) $ U.readFile file -> if test -> then putStr html -> else if null postid -> then do -> postid <- postIt url blogid user pw title html cats pub -> putStrLn $ "post Id: " ++ postid -> else do -> result <- updateIt url postid user pw title html cats pub -> unless result $ putStrLn "update failed!" - -And the main program is simply: - -> main = cmdArgs info [bl] >>= blogLiterately -> where info = "BlogLierately v0.3, (C) Robert Greayer 2010\n" ++ -> "This program comes with ABSOLUTELY NO WARRANTY\n" - -I can run it to get some help: - -[markdown]: http://daringfireball.net/projects/markdown/ -[pandoc]: http://johnmacfarlane.net/pandoc/ "Pandoc" -[hackage]: http://hackage.haskell.org/packages/hackage.html -[haddock]: http://www.haskell.org/haddock/ -[hscolour]: http://www.cs.york.ac.uk/fp/darcs/hscolour/ -[metaweblog]: http://www.xmlrpc.com/metaWeblogApi -[haxr]: http://www.haskell.org/haxr/ -[hackage-haxr]: http://hackage.haskell.org/package/haxr -[cmdargs]: http://community.haskell.org/~ndm/cmdargs/ -[haxml]: http://www.cs.york.ac.uk/fp/HaXml/ +BlogLiterately is a tool for uploading blog posts to servers that+support the MetaWeblog API (such as WordPress-based blogs and many+others). It also handles syntax highlighting of Haskell and other+languages.++> {-# LANGUAGE TypeOperators #-}+> {-# LANGUAGE DeriveDataTypeable #-}+> {-# LANGUAGE RecordWildCards #-}+> module Main where++We need [Pandoc][] for parsing [Markdown][]:++> import Text.Pandoc+> import Text.Pandoc.Highlighting ( highlight, formatHtmlBlock )++And [hscolour][] for highlighting:++> import Language.Haskell.HsColour ( hscolour, Output(..) )+> import Language.Haskell.HsColour.Colourise ( defaultColourPrefs )++To post to a blog, we need the [MetaWeblog][] API, which is an+XML-RPC-based protocol for interacting with blogs.++We'll use the Haskell XML-RPC library, [HaXR][], by Bjorn Bringert,+(on [hackage][hackage-haxr]).++> import Network.XmlRpc.Client ( remote )+> import Network.XmlRpc.Internals ( XmlRpcType(toValue) )++We use Neil Mitchell's [CmdArgs][] library for processing command-line+arguments:++> import System.Console.CmdArgs++We also need to parse and manipulate XHTML, so we'll use Malcolm+Wallace's [HaXml][] XML combinators, and blaze-html for rendering+HTML:++> import Text.XML.HaXml+> import Text.XML.HaXml.Posn ( noPos )+> import Text.Blaze.Html.Renderer.String ( renderHtml )++Finally, some miscellaneous/standard imports:++> import Control.Arrow ( first, (>>>), arr+> , Kleisli(..), runKleisli )+> import qualified Control.Category as C ( Category, id )+> import Control.Monad ( liftM, unless )+> import Control.Monad.IO.Class ( liftIO )+> import Control.Monad.Trans.Reader ( ReaderT, runReaderT, ask )+> import Data.Functor ( (<$>) )+> import Data.List ( isPrefixOf, intercalate )+> import System.IO+> import qualified System.IO.UTF8 as U ( readFile )+> import System.Process ( ProcessHandle, waitForProcess+> , runInteractiveCommand )+> import Text.ParserCombinators.Parsec++The program will read in a literate Haskell file, use Pandoc to parse+it as markdown, and, if it is using hscolour to for the Haskell+pieces, hscolour to transform those. Pandoc turns its input into a+structure of type:++ [haskell]+ data Pandoc = Pandoc Meta [Block]+ +where a `Block` (the interesting bit, for our purposes) looks like:++ [haskell]+ -- | Block element.+ data Block+ = Plain [Inline] -- ^ Plain text, not a paragraph+ | Para [Inline] -- ^ Paragraph+ | CodeBlock Attr String -- ^ Code block (literal) with attributes+ | RawBlock Format String -- ^ Raw block+ | BlockQuote [Block] -- ^ Block quote (list of blocks)+ | OrderedList ListAttributes [[Block]] -- ^ Ordered list (attributes+ -- and a list of items, each a list of blocks)+ | BulletList [[Block]] -- ^ Bullet list (list of items, each+ -- a list of blocks)+ | DefinitionList [([Inline],[[Block]])] -- ^ Definition list+ -- Each list item is a pair consisting of a+ -- term (a list of inlines) and one or more+ -- definitions (each a list of blocks)+ | Header Int [Inline] -- ^ Header - level (integer) and text (inlines)+ | HorizontalRule -- ^ Horizontal rule+ | Table [Inline] [Alignment] [Double] [TableCell] [[TableCell]] -- ^ Table,+ -- with caption, column alignments,+ -- relative column widths (0 = default),+ -- column headers (each a list of blocks), and+ -- rows (each a list of lists of blocks)+ | Null -- ^ Nothing+ deriving (Eq, Ord, Read, Show, Typeable, Data GENERIC)++The literate Haskell that Pandoc finds in a file ends up in various+`CodeBlock` elements of the `Pandoc` document. Other code can also+wind up in `CodeBlock` elements -- normal markdown formatted code.+The `Attr` component has metadata about what's in the code block:++ [haskell]+ type Attr = ( String, -- code block identifier+ , [String] -- list of code classes+ , [(String, String)] -- name/value pairs+ )++Thanks to some feedback from the Pandoc author, John MacFarlane, I+learned that the CodeBlock *may* contain markers about the kind of+code contained within the block. LHS (bird-style or LaTex style) will+always have an `Attr` of the form `("",["sourceCode","haskell"],[])`,+and other `CodeBlock` elements are the markdown code blocks *may* have+an identifier, classes, or key/value pairs. Pandoc captures this info+when the file contains code blocks in the delimited (rather than+indented) format, which allows an optional meta-data specification,+e.g.++~~~~~~~~~~~+~~~~~~~ { .bash }+x=$1+echo $x+~~~~~~~+~~~~~~~~~~~++Although Pandoc supports the above format for marking code blocks (and+annotating the kind of code within the block) I'll also keep my+notation as another option for use with indented blocks, i.e. if you+write:++<pre><code>+ [haskell]+ foo :: String -> String+</code></pre>++it is a Haskell block. You can also use other annotations, *e.g.*++<pre><code>+ [cpp]+ cout << "Hello World!";+</code></pre>++If highlighting-kate is specified for highlighting Haskell blocks, the+distinction between the literate blocks and the delimited blocks is+lost (this is simply how the Pandoc highlighting module currently+works).++I'll adopt the rule that if you specify a class or classes using+Pandoc's delimited code block syntax, I'll assume that there is no+additional tag within the block in Blog Literately syntax. I still+need my `unTag` function to parse the code block.++> unTag :: String -> (String, String)+> unTag s = either (const ("",s)) id $ parse tag "" s+> where+> tag = do+> tg <- between (char '[') (char ']') $ many $ noneOf "[]"+> skipMany $ oneOf " \t"+> (string "\r\n" <|> string "\n")+> txt <- many $ anyToken+> eof+> return (tg,txt)++To highlight the syntax using hscolour (which produces HTML), I'm+going to need to transform the `String` from a `CodeBlock` element to+a `String` suitable for the `RawHtml` element (because the hscolour+library transforms Haskell text to HTML). Pandoc strips off the+prepended > characters from the literate Haskell, so I need to put+them back, and also tell hscolour whether the source it is colouring+is literate or not. The hscolour function looks like:++ [haskell]+ hscolour :: Output -- ^ Output format.+ -> ColourPrefs -- ^ Colour preferences...+ -> Bool -- ^ Whether to include anchors.+ -> Bool -- ^ Whether output document is partial or complete.+ -> String -- ^ Title for output.+ -> Bool -- ^ Whether input document is literate haskell+ -> String -- ^ Haskell source code.+ -> String -- ^ Coloured Haskell source code.++Since I still don't like the `ICSS` output from hscolour, I'm going to+provide two options for hscolouring to users: one that simply uses+hscolour's `CSS` format, so the user can provide definitions in their+blog's stylesheet to control the rendering, and a post-processing+option to transform the `CSS` class-based rendering into a inline+style based rendering (for people who can't update their stylesheet).+`colourIt` performs the initial transformation:++> colourIt literate srcTxt =+> hscolour CSS defaultColourPrefs False True "" literate srcTxt'+> where srcTxt' | literate = prepend srcTxt+> | otherwise = srcTxt++Prepending the literate Haskell markers on the source:++> prepend = unlines . map ("> " ++) . lines++Hscolour uses HTML `span` elements and CSS classes like 'hs-keyword'+or `hs-keyglyph` to markup Haskell code. What I want to do is take+each marked `span` element and replace the `class` attribute with an+inline `style` element that has the markup I want for that kind of+source. Style preferences are specified as a list of name/value+pairs:++> type StylePrefs = [(String,String)]++Here's a default style that produces something like what the source+listings on Hackage look like:++> defaultStylePrefs = [+> ("hs-keyword","color: blue; font-weight: bold;")+> , ("hs-keyglyph","color: red;")+> , ("hs-layout","color: red;")+> , ("hs-comment","color: green;")+> , ("hs-conid", "")+> , ("hs-varid", "")+> , ("hs-conop", "")+> , ("hs-varop", "")+> , ("hs-str", "color: teal;")+> , ("hs-chr", "color: teal;")+> , ("hs-number", "")+> , ("hs-cpp", "")+> , ("hs-selection", "")+> , ("hs-variantselection", "")+> , ("hs-definition", "")]++I can read these preferences in from a file using the `Read` instance+for `StylePrefs`. I could handle errors better, but this should work:++> getStylePrefs "" = return defaultStylePrefs+> getStylePrefs fname = liftM read (U.readFile fname)++Hscolour produces a `String` of HTML. To 'bake' the styles into the+HTML, we need to parse it, manipulate it and then re-render it as a+`String`. We use HaXml to do all of this:++> bakeStyles :: StylePrefs -> String -> String+> bakeStyles prefs s = verbatim $ filtDoc (xmlParse "bake-input" s)+> where+>+> -- filter the document (an Hscoloured fragment of Haskell source)+> filtDoc (Document p s e m) = c where+> [c] = filts (CElem e noPos)+>+> -- the filter is a fold of individual filters for each CSS class+> filts = mkElem "pre" [(foldXml $ foldl o keep $ map filt prefs) `o` replaceTag "code"]+>+> -- an individual filter replaces the attributes of a tag with+> -- a style attribute when it has a specific 'class' attribute.+> filt (cls,style) =+> replaceAttrs [("style",style)] `when`+> (attrval $ (N "class", AttValue [Left cls]))++Highlighting-Kate uses <br/> in code blocks to indicate newlines.+WordPress (if not other software) chooses to strip them away when+found in <pre> sections of uploaded HTML. So we need to turn them+back to newlines.++> replaceBreaks :: String -> String+> replaceBreaks s = verbatim $ filtDoc (xmlParse "input" s)+> where+> -- filter the document (a highlighting-kate highlighted fragment of+> -- haskell source)+> filtDoc (Document p s e m) = c where+> [c] = filts (CElem e noPos)+> filts = foldXml (literal "\n" `when` tag "br")++Note to self: the above is a function that could be made better in a+few ways and then factored out into a library. A way to handle the+above would be to allow the preferences to be specified as an actual+CSS style sheet, which then would be baked into the HTML. Such a+function could be separately useful, and could be used to 'bake' in+the highlighting-kate styles.++To completely colourise/highlight a `CodeBlock` we now can create a+function that transforms a `CodeBlock` into a `RawHtml` block, where+the content contains marked up Haskell (possibly with literate+markers), or marked up non-Haskell, if highlighting of non-Haskell has+been selected.++> colouriseCodeBlock :: HsHighlight -> Bool -> Block -> Block+> colouriseCodeBlock hsHighlight otherHighlight b@(CodeBlock attr@(_,classes,_) s)+>+> | tag == "haskell" || haskell+> = case hsHighlight of+> HsColourInline style ->+> RawBlock "html" $ bakeStyles style $ colourIt lit src+> HsColourCSS -> RawBlock "html" $ colourIt lit src+> HsNoHighlight -> RawBlock "html" $ simpleHTML hsrc+> HsKate -> if null tag+> then myHighlightK attr hsrc+> else myHighlightK ("",tag:classes,[]) hsrc+>+> | otherHighlight+> = case tag of+> "" -> myHighlightK attr src+> t -> myHighlightK ("",[t],[]) src+>+> | otherwise+> = RawBlock "html" $ simpleHTML src+>+> where+> (tag,src)+> | null classes = unTag s+> | otherwise = ("",s)+> hsrc+> | lit = prepend src+> | otherwise = src+> lit = "sourceCode" `elem` classes+> haskell = "haskell" `elem` classes+> simpleHTML s = "<pre><code>" ++ s ++ "</code></pre>"+> myHighlightK attr s = case highlight formatHtmlBlock attr s of+> Nothing -> RawBlock "html" $ simpleHTML s+> Just html -> RawBlock "html" $ replaceBreaks $ renderHtml html+>+> colouriseCodeBlock _ _ b = b++Colourising a `Pandoc` document is simply:++> colourisePandoc hsHighlight otherHighlight (Pandoc m blocks) =+> Pandoc m $ map (colouriseCodeBlock hsHighlight otherHighlight) blocks++WordPress can render LaTeX, but expects it in a special (non-standard)+format (`\$latex foo\$`). The `wpTeXify` function formats LaTeX code+using this format so that it can be processed by WordPress.++> wpTeXify :: Pandoc -> Pandoc+> wpTeXify = bottomUp formatDisplayTex . bottomUp formatInlineTex+> where formatInlineTex :: [Inline] -> [Inline]+> formatInlineTex (Math InlineMath tex : is)+> = (Str $ "$latex " ++ unPrefix "latex" tex ++ "$") : is+> formatInlineTex is = is+>+> formatDisplayTex :: [Block] -> [Block]+> formatDisplayTex (Para [Math DisplayMath tex] : bs)+> = RawBlock "html" "<p><div style=\"text-align: center\">"+> : Plain [Str $ "$latex " ++ "\\displaystyle " ++ unPrefix "latex" tex ++ "$"]+> : RawBlock "html" "</div></p>"+> : bs+> formatDisplayTex bs = bs+>+> unPrefix pre s+> | pre `isPrefixOf` s = drop (length pre) s+> | otherwise = s++The next bit of code enables using code blocks marked with `[ghci]` as+input to ghci and then inserting the results. This code was mostly+stolen from lhs2TeX.++> type ProcessInfo = (Handle, Handle, Handle, ProcessHandle)++First, a way to evaluate an expression using an external ghci process.++> ghciEval :: String -> ReaderT ProcessInfo IO String+> ghciEval expr = do+> (pin, pout, _, _) <- ask+> let script = "putStrLn " ++ show magic ++ "\n"+> ++ expr ++ "\n"+> ++ "putStrLn " ++ show magic ++ "\n"+> liftIO $ do+> hPutStr pin script+> hFlush pin+> extract' pout+>+> withGhciProcess :: FilePath -> ReaderT ProcessInfo IO a -> IO a+> withGhciProcess f m = do+> isLit <- isLiterate f+> pi <- runInteractiveCommand $ "ghci -v0 -ignore-dot-ghci "+> ++ (if isLit then f else "")+> res <- runReaderT m pi+> stopProcess pi+> return res+>+> isLiterate :: FilePath -> IO Bool+> isLiterate f = (any ("> " `isPrefixOf`) . lines) <$> readFile f+>+> stopProcess :: ProcessInfo -> IO ()+> stopProcess (pin,_,_,pid) = do+> hPutStrLn pin ":q"+> hFlush pin+> _ <- waitForProcess pid -- ignore exit code+> return ()++To extract the answer from @ghci@'s output we use a simple technique+which should work in most cases: we print the string |magic| before+and after the expression we are interested in. We assume that+everything that appears before the first occurrence of |magic| on the+same line is the prompt, and everything between the first |magic| and+the second |magic| plus prompt is the result we look for.++> magic :: String+> magic = "!@#$^&*"+>+> extract' :: Handle -> IO String+> extract' h = fmap (extract . unlines) (readMagic 2)+> where+> readMagic :: Int -> IO [String]+> readMagic 0 = return []+> readMagic n = do+> l <- hGetLine h+> let n' | (null . snd . breaks (isPrefixOf magic)) l = n+> | otherwise = n - 1+> fmap (l:) (readMagic n')+>+> extract :: String -> String+> extract s = v+> where (t, u) = breaks (isPrefixOf magic) s+> -- t contains everything up to magic, u starts with magic+> -- |u' = tail (dropWhile (/='\n') u)|+> pre = reverse . takeWhile (/='\n') . reverse $ t+> prelength = if null pre then 0 else length pre + 1+> -- pre contains the prefix of magic on the same line+> u' = drop (length magic + prelength) u+> -- we drop the magic string, plus the newline, plus the prefix+> (v, _) = breaks (isPrefixOf (pre ++ magic)) u'+> -- we look for the next occurrence of prefix plus magic+>+> breaks :: ([a] -> Bool) -> [a] -> ([a], [a])+> breaks p [] = ([], [])+> breaks p as@(a : as')+> | p as = ([], as)+> | otherwise = first (a:) $ breaks p as'++Finally, a function which takes the path to the `.lhs` source and its+representation as a `Pandoc` document, finds any `[ghci]` blocks in+it, runs them through `ghci`, and formats the results as an+interactive `ghci` session.++> formatInlineGhci :: FilePath -> Pandoc -> IO Pandoc+> formatInlineGhci f = withGhciProcess f . bottomUpM formatInlineGhci'+> where+> formatInlineGhci' :: Block -> ReaderT ProcessInfo IO Block+> formatInlineGhci' b@(CodeBlock attr s)+> | tag == "ghci" = do+> results <- zip inputs <$> mapM ghciEval inputs+> return $ CodeBlock attr (intercalate "\n" $ map formatGhciResult results)+>+> | otherwise = return b+>+> where (tag,src) = unTag s+> inputs = lines src+>+> formatInlineGhci' b = return b+>+> formatGhciResult (input, output)+> = "<span style=\"color: gray;\">ghci></span> " ++ input ++ (unlines . map (" "++) . lines) output -- XXX this should be configurable!++A useful arrow utility, for running some part of a pipeline+conditionally:++> whenA :: C.Category (~>) => (a ~> a) -> Bool -> (a ~> a)+> whenA a p | p = a+> | otherwise = C.id++Finally, putting everything together to transform a complete input+document string to an HTML output string. Note this may involve+running `ghci`.++> xformDoc :: BlogLiterately -> (String -> IO String)+> xformDoc bl@(BlogLiterately {..}) = runKleisli $+> arr fixLineEndings+> >>> arr (readMarkdown parseOpts) -- from Pandoc+> >>> arr wpTeXify `whenA` wplatex+> >>> Kleisli (formatInlineGhci file) `whenA` ghci+> -- >>> Kleisli (uploadAllImages bl)+> >>> arr (colourisePandoc hsHighlight otherHighlight)+> >>> arr (writeHtml writeOpts) -- from Pandoc+> >>> arr renderHtml+> where+> writeOpts = defaultWriterOptions+> { writerReferenceLinks = True }+> parseOpts = defaultParserState+> { stateLiterateHaskell = True }+>+> -- readMarkdown is picky about line endings+> fixLineEndings [] = []+> fixLineEndings ('\r':'\n':cs) = '\n':fixLineEndings cs+> fixLineEndings (c:cs) = c:fixLineEndings cs++The metaWeblog API defines `newPost` and `editPost` procedures that+look like:++ [other]+ metaWeblog.newPost (blogid, username, password, struct, publish)+ returns string+ metaWeblog.editPost (postid, username, password, struct, publish)+ returns true++For WordPress blogs, the `blogid` is ignored. The user name and+password are simply strings, and `publish` is a flag indicating+whether to load the post as a draft, or to make it public immediately.+The `postid` is an identifier string which is assigned when you+initially create a post. The interesting bit is the `struct` field,+which is an XML-RPC structure defining the post along with some+meta-data, like the title. I want be able to provide the post body, a+title, and lists of categories and tags. For the body and title, we+could just let HaXR convert the values automatically into the XML-RPC+`Value` type, since they all have the same Haskell type (`String`) and+thus can be put into a list. But the categories and tags are lists of+strings, so we need to explicitly convert everything to a `Value`,+then combine:++> mkPost title text categories tags page =+> mkArray "categories" categories+> ++ mkArray "mt_keywords" tags+> ++ [ ("title", toValue title)+> , ("description", toValue text)+> ]+> ++ [ ("post_type", toValue "page") | page ]+>+> mkArray _ [] = []+> mkArray name values = [(name, toValue values)]++The HaXR library exports a function for invoking XML-RPC procedures:++ [haskell]+ remote :: Remote a =>+ String -- ^ Server URL. May contain username and password on+ -- the format username:password\@ before the hostname.+ -> String -- ^ Remote method name.+ -> a -- ^ Any function+ -- @(XmlRpcType t1, ..., XmlRpcType tn, XmlRpcType r) =>+ -- t1 -> ... -> tn -> IO r@++The function requires an URL and a method name, and returns a function+of type `Remote a => a`. Based on the instances defined for `Remote`,+any function with zero or more parameters in the class `XmlRpcType`+and a return type of `XmlRpcType r => IO r` will work, which means you+can simply 'feed' `remote` additional arguments as required by the+remote procedure, and as long as you make the call in an IO context,+it will typecheck. `postIt` calls `metaWeblog.newPost` or+`metaWeblog.editPost` (or simply prints the HTML to stdout) as+appropriate:++> postIt :: BlogLiterately -> String -> IO ()+> postIt (BlogLiterately{..}) html =+> case blog of+> Nothing -> putStr html+> Just url ->+> case postid of+> Nothing -> do+> pid <- remote url "metaWeblog.newPost" blogid user password+> (mkPost title html categories tags page) publish+> putStrLn $ "Post ID: " ++ pid+> Just pid -> do+> success <- remote url "metaWeblog.editPost" pid user password+> (mkPost title html categories tags page) publish+> unless success $ putStrLn "update failed!"++There are four modes of Haskell highlighting:++> data HsHighlight =+> HsColourInline StylePrefs+> | HsColourCSS+> | HsKate+> | HsNoHighlight+> deriving (Data,Typeable,Show,Eq)++And two modes for other code (off or on!).++To create a command line program, we capture the command line controls+in a type:++> data BlogLiterately = BlogLiterately+> { style :: String -- name of a style file+> , hsHighlight :: HsHighlight -- Haskell highlighting mode+> , otherHighlight :: Bool -- use highlighting-kate for non-Haskell?+> , wplatex :: Bool -- format LaTeX for WordPress?+> , ghci :: Bool -- automatically generate ghci sessions?+> -- , uploadImages :: Bool -- automatically upload images?+> , categories :: [String] -- categories for the post+> , tags :: [String] -- tags for the post+> , blogid :: String -- blog-specific identifier (e.g. for blogging+> -- software handling multiple blogs)+> , blog :: Maybe String -- blog xmlrpc URL+> , user :: String -- blog user name+> , password :: String -- blog password+> , title :: String -- post title+> , file :: String -- file to post+> , postid :: Maybe String -- id of a post to update+> , page :: Bool -- create a "page" instead of a post+> , publish :: Bool -- Should the post be published, or+> -- loaded as a draft?+> }+> deriving (Show,Data,Typeable)++And using CmdArgs, this bit of impure evil defines how the command+line arguments work:++> bl = BlogLiterately+> { style = "" &= help "style specification (for --hscolour-icss)"+> &= typFile+> , hsHighlight = enum+> [ (HsColourInline defaultStylePrefs)+> &= explicit+> &= name "hscolour-icss"+> &= help "highlight haskell: hscolour, inline style (default)"+> , HsColourCSS+> &= explicit+> &= name "hscolour-css"+> &= help "highlight haskell: hscolour, separate stylesheet"+> , HsNoHighlight+> &= explicit+> &= name "hs-nohighlight"+> &= help "no haskell highlighting"+> , HsKate+> &= explicit+> &= name "hs-kate"+> &= help "highlight haskell with highlighting-kate"+> ]+> , otherHighlight = enum+> [ True+> &= explicit+> &= name "other-kate"+> &= help "highlight other code with highlighting-kate"+> ]+> , wplatex = def &= help "reformat inline LaTeX the way WordPress expects"+> , ghci = def &= help "run [ghci] blocks through ghci and include output"+> -- , uploadImages = def &= name "upload-images" &= explicit &= help "upload local images"+> , page = def &= help "create a \"page\" instead of a post (WordPress only)"+> , publish = def &= help "publish post (otherwise it's uploaded as a draft)"+> , categories = def+> &= explicit+> &= name "category"+> &= help "post category (can specify more than one)"+> , tags = def+> &= explicit+> &= name "tag"+> &= help "tag (can specify more than one)"+>+> , blogid = "default" &= help "Blog specific identifier" &= typ "ID"+> , postid = def &= help "Post to replace (if any)" &= typ "ID"+>+> , blog = def &= typ "URL" &= help "blog XML-RPC url (if omitted, html goes to stdout)"+> , user = def &= typ "USER" &= help "user name"+> , password = def &= typ "PASSWORD" &= help "password"+> , title = def &= typ "TITLE" &= help "post title"+> , file = def &= argPos 0 &= typ "FILE"+> }+> &= program "BlogLiterately"+> &= summary ("BlogLierately v0.4, (c) Robert Greayer 2008-2010, Brent Yorgey 2012\n" +++> "This program comes with ABSOLUTELY NO WARRANTY\n")++The main blogging function uses the information captured in the+`BlogLiterately` type to read the style preferences, read the input+file and transform it, and post it to the blog:++> blogLiterately bl@(BlogLiterately {..}) = do+> prefs <- getStylePrefs style+> let hsHighlight' = case hsHighlight of+> HsColourInline _ -> HsColourInline prefs+> _ -> hsHighlight+> bl' = bl { hsHighlight = hsHighlight' }+> html <- xformDoc bl' =<< U.readFile file+> postIt bl html++And the main program is simply:++> main = cmdArgs bl >>= blogLiterately++[markdown]: http://daringfireball.net/projects/markdown/+[pandoc]: http://johnmacfarlane.net/pandoc/ "Pandoc"+[hackage]: http://hackage.haskell.org/packages/hackage.html+[haddock]: http://www.haskell.org/haddock/+[hscolour]: http://www.cs.york.ac.uk/fp/darcs/hscolour/+[metaweblog]: http://www.xmlrpc.com/metaWeblogApi+[haxr]: http://www.haskell.org/haxr/+[hackage-haxr]: http://hackage.haskell.org/package/haxr+[cmdargs]: http://community.haskell.org/~ndm/cmdargs/+[haxml]: http://www.cs.york.ac.uk/fp/HaXml/
+ style/hs-style view
@@ -0,0 +1,16 @@+[ ("hs-keyword","color: blue; font-weight: bold;")+, ("hs-keyglyph","color: red;")+, ("hs-layout","color: red;")+, ("hs-comment","color: green;")+, ("hs-conid","")+, ("hs-varid","")+, ("hs-conop","")+, ("hs-varop","")+, ("hs-str","color: teal;")+, ("hs-chr","color: teal;")+, ("hs-number","")+, ("hs-cpp","")+, ("hs-selection","")+, ("hs-variantselection","")+, ("hs-definition","")+]
+ style/hscolour.css view
@@ -0,0 +1,6 @@+.hs-keyglyph, .hs-layout {color: red;}+.hs-keyword {color: blue;}+.hs-comment, .hs-comment a {color: green;}+.hs-str, .hs-chr {color: teal;}+.hs-keyword,.hs-conid, .hs-varid, .hs-conop, .hs-varop {}+.hs-num, .hs-cpp, .hs-sel, .hs-definition {}
+ style/kate.css view
@@ -0,0 +1,23 @@+/* this file was derived from highlighting-kate which is Copyright+ John MacFarlane. Approximately the same file, along with other + stylesheets, are available in the highlighting-kate package on+ hackage. */+table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode, table.sourceCode pre + { margin: 0; padding: 0; border: 0; vertical-align: baseline; border: none; }+td.lineNumbers { border-right: 1px solid #AAAAAA; text-align: right; color: #AAAAAA; padding-right: 5px; padding-left: 5px; }+td.sourceCode { padding-left: 5px; }+pre.sourceCode { }+pre.sourceCode span.Normal { }+pre.sourceCode span.Keyword { color: #007020; font-weight: bold; } +pre.sourceCode span.DataType { color: #902000; }+pre.sourceCode span.DecVal { color: #40a070; }+pre.sourceCode span.BaseN { color: #40a070; }+pre.sourceCode span.Float { color: #40a070; }+pre.sourceCode span.Char { color: #4070a0; }+pre.sourceCode span.String { color: #4070a0; }+pre.sourceCode span.Comment { color: #60a0b0; font-style: italic; }+pre.sourceCode span.Others { color: #007020; }+pre.sourceCode span.Alert { color: red; font-weight: bold; }+pre.sourceCode span.Function { color: #06287e; }+pre.sourceCode span.RegionMarker { }+pre.sourceCode span.Error { color: red; font-weight: bold; }