├── .github └── workflows │ ├── full-release.yml │ ├── pdf.yml │ └── release.yml ├── CMakeLists.txt ├── LICENSE ├── README.md └── scripts ├── config.yml ├── offline-doc-generator.py └── requirements.txt /.github/workflows/full-release.yml: -------------------------------------------------------------------------------- 1 | name: Zipped Release Complete 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | build: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Checkout 11 | uses: actions/checkout@v2 12 | 13 | - name: Install wkthtmltopdf 14 | run: | 15 | sudo apt-get install -y xfonts-base xfonts-75dpi 16 | wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.bionic_amd64.deb 17 | sudo dpkg -i wkhtmltox_0.12.6-1.bionic_amd64.deb 18 | 19 | - name: Install Liberation Fonts 20 | run: | 21 | sudo apt-get update -y 22 | sudo apt-get install -y fonts-liberation 23 | 24 | - name: Run .py script for Doc Generation 25 | run: | 26 | cmake . -Bbuild 27 | cmake --build build 28 | 29 | - name: Upload zipped doc file to release 30 | uses: svenstaro/upload-release-action@v2 31 | with: 32 | repo_token: ${{ secrets.GITHUB_TOKEN }} 33 | file: build/*.zip 34 | tag: Docs-Release 35 | overwrite: true 36 | file_glob: true 37 | body: "This is a release containing both the zip files (one for the Docs Generated, another containing the Generated PDFs) using Github Actions." -------------------------------------------------------------------------------- /.github/workflows/pdf.yml: -------------------------------------------------------------------------------- 1 | name: pdf 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | build: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Checkout 11 | uses: actions/checkout@v2 12 | 13 | - name: Install wkthtmltopdf 14 | run: | 15 | sudo apt-get install -y xfonts-base xfonts-75dpi 16 | wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.bionic_amd64.deb 17 | sudo dpkg -i wkhtmltox_0.12.6-1.bionic_amd64.deb 18 | 19 | - name: Install Liberation Fonts 20 | run: | 21 | sudo apt-get update -y 22 | sudo apt-get install -y fonts-liberation 23 | 24 | - name: Run .py script for Doc Generation 25 | run: | 26 | cmake . -Bbuild 27 | cmake --build build 28 | 29 | - name: Upload zipped doc file to release 30 | uses: svenstaro/upload-release-action@v2 31 | with: 32 | repo_token: ${{ secrets.GITHUB_TOKEN }} 33 | file: build/PDF-Offline-Manual.zip 34 | asset_name: PDF-Offline-Manual.zip 35 | tag: Docs-Release 36 | overwrite: true 37 | body: "This is a release containing the PDF version of the Docs Generated using Github Actions." 38 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: release 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | workflow_dispatch: 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v2 14 | 15 | - name: Install wkthtmltopdf 16 | run: | 17 | sudo apt-get install -y xfonts-base xfonts-75dpi 18 | wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.bionic_amd64.deb 19 | sudo dpkg -i wkhtmltox_0.12.6-1.bionic_amd64.deb 20 | 21 | - name: Install Liberation Fonts 22 | run: | 23 | sudo apt-get update -y 24 | sudo apt-get install -y fonts-liberation 25 | 26 | - name: Run .py script for Doc Generation 27 | run: | 28 | cmake . -Bbuild 29 | cmake --build build 30 | 31 | - name: Upload zipped doc file to release 32 | uses: svenstaro/upload-release-action@v2 33 | with: 34 | repo_token: ${{ secrets.GITHUB_TOKEN }} 35 | file: build/Generated-Offline-Manual.zip 36 | asset_name: Generated-Offline-Manual.zip 37 | tag: Docs-Release 38 | overwrite: true 39 | body: "This is a release containing the Docs Generated using Github Actions." 40 | 41 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | find_package(Python3 COMPONENTS Interpreter) 4 | 5 | set(Doc_Script ${CMAKE_CURRENT_SOURCE_DIR}/scripts/offline-doc-generator.py) 6 | 7 | execute_process(COMMAND ${Python3_EXECUTABLE} -m pip install -r ${CMAKE_CURRENT_SOURCE_DIR}/scripts/requirements.txt) 8 | 9 | add_custom_target(doc ALL COMMAND ${Python3_EXECUTABLE} ${Doc_Script}) 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | Attribution-ShareAlike 3.0 Unported 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR 10 | DAMAGES RESULTING FROM ITS USE. 11 | 12 | License 13 | 14 | THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE 15 | COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY 16 | COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS 17 | AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. 18 | 19 | BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE 20 | TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY 21 | BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS 22 | CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND 23 | CONDITIONS. 24 | 25 | 1. Definitions 26 | 27 | a. "Adaptation" means a work based upon the Work, or upon the Work and 28 | other pre-existing works, such as a translation, adaptation, 29 | derivative work, arrangement of music or other alterations of a 30 | literary or artistic work, or phonogram or performance and includes 31 | cinematographic adaptations or any other form in which the Work may be 32 | recast, transformed, or adapted including in any form recognizably 33 | derived from the original, except that a work that constitutes a 34 | Collection will not be considered an Adaptation for the purpose of 35 | this License. For the avoidance of doubt, where the Work is a musical 36 | work, performance or phonogram, the synchronization of the Work in 37 | timed-relation with a moving image ("synching") will be considered an 38 | Adaptation for the purpose of this License. 39 | b. "Collection" means a collection of literary or artistic works, such as 40 | encyclopedias and anthologies, or performances, phonograms or 41 | broadcasts, or other works or subject matter other than works listed 42 | in Section 1(f) below, which, by reason of the selection and 43 | arrangement of their contents, constitute intellectual creations, in 44 | which the Work is included in its entirety in unmodified form along 45 | with one or more other contributions, each constituting separate and 46 | independent works in themselves, which together are assembled into a 47 | collective whole. A work that constitutes a Collection will not be 48 | considered an Adaptation (as defined below) for the purposes of this 49 | License. 50 | c. "Creative Commons Compatible License" means a license that is listed 51 | at https://creativecommons.org/compatiblelicenses that has been 52 | approved by Creative Commons as being essentially equivalent to this 53 | License, including, at a minimum, because that license: (i) contains 54 | terms that have the same purpose, meaning and effect as the License 55 | Elements of this License; and, (ii) explicitly permits the relicensing 56 | of adaptations of works made available under that license under this 57 | License or a Creative Commons jurisdiction license with the same 58 | License Elements as this License. 59 | d. "Distribute" means to make available to the public the original and 60 | copies of the Work or Adaptation, as appropriate, through sale or 61 | other transfer of ownership. 62 | e. "License Elements" means the following high-level license attributes 63 | as selected by Licensor and indicated in the title of this License: 64 | Attribution, ShareAlike. 65 | f. "Licensor" means the individual, individuals, entity or entities that 66 | offer(s) the Work under the terms of this License. 67 | g. "Original Author" means, in the case of a literary or artistic work, 68 | the individual, individuals, entity or entities who created the Work 69 | or if no individual or entity can be identified, the publisher; and in 70 | addition (i) in the case of a performance the actors, singers, 71 | musicians, dancers, and other persons who act, sing, deliver, declaim, 72 | play in, interpret or otherwise perform literary or artistic works or 73 | expressions of folklore; (ii) in the case of a phonogram the producer 74 | being the person or legal entity who first fixes the sounds of a 75 | performance or other sounds; and, (iii) in the case of broadcasts, the 76 | organization that transmits the broadcast. 77 | h. "Work" means the literary and/or artistic work offered under the terms 78 | of this License including without limitation any production in the 79 | literary, scientific and artistic domain, whatever may be the mode or 80 | form of its expression including digital form, such as a book, 81 | pamphlet and other writing; a lecture, address, sermon or other work 82 | of the same nature; a dramatic or dramatico-musical work; a 83 | choreographic work or entertainment in dumb show; a musical 84 | composition with or without words; a cinematographic work to which are 85 | assimilated works expressed by a process analogous to cinematography; 86 | a work of drawing, painting, architecture, sculpture, engraving or 87 | lithography; a photographic work to which are assimilated works 88 | expressed by a process analogous to photography; a work of applied 89 | art; an illustration, map, plan, sketch or three-dimensional work 90 | relative to geography, topography, architecture or science; a 91 | performance; a broadcast; a phonogram; a compilation of data to the 92 | extent it is protected as a copyrightable work; or a work performed by 93 | a variety or circus performer to the extent it is not otherwise 94 | considered a literary or artistic work. 95 | i. "You" means an individual or entity exercising rights under this 96 | License who has not previously violated the terms of this License with 97 | respect to the Work, or who has received express permission from the 98 | Licensor to exercise rights under this License despite a previous 99 | violation. 100 | j. "Publicly Perform" means to perform public recitations of the Work and 101 | to communicate to the public those public recitations, by any means or 102 | process, including by wire or wireless means or public digital 103 | performances; to make available to the public Works in such a way that 104 | members of the public may access these Works from a place and at a 105 | place individually chosen by them; to perform the Work to the public 106 | by any means or process and the communication to the public of the 107 | performances of the Work, including by public digital performance; to 108 | broadcast and rebroadcast the Work by any means including signs, 109 | sounds or images. 110 | k. "Reproduce" means to make copies of the Work by any means including 111 | without limitation by sound or visual recordings and the right of 112 | fixation and reproducing fixations of the Work, including storage of a 113 | protected performance or phonogram in digital form or other electronic 114 | medium. 115 | 116 | 2. Fair Dealing Rights. Nothing in this License is intended to reduce, 117 | limit, or restrict any uses free from copyright or rights arising from 118 | limitations or exceptions that are provided for in connection with the 119 | copyright protection under copyright law or other applicable laws. 120 | 121 | 3. License Grant. Subject to the terms and conditions of this License, 122 | Licensor hereby grants You a worldwide, royalty-free, non-exclusive, 123 | perpetual (for the duration of the applicable copyright) license to 124 | exercise the rights in the Work as stated below: 125 | 126 | a. to Reproduce the Work, to incorporate the Work into one or more 127 | Collections, and to Reproduce the Work as incorporated in the 128 | Collections; 129 | b. to create and Reproduce Adaptations provided that any such Adaptation, 130 | including any translation in any medium, takes reasonable steps to 131 | clearly label, demarcate or otherwise identify that changes were made 132 | to the original Work. For example, a translation could be marked "The 133 | original work was translated from English to Spanish," or a 134 | modification could indicate "The original work has been modified."; 135 | c. to Distribute and Publicly Perform the Work including as incorporated 136 | in Collections; and, 137 | d. to Distribute and Publicly Perform Adaptations. 138 | e. For the avoidance of doubt: 139 | 140 | i. Non-waivable Compulsory License Schemes. In those jurisdictions in 141 | which the right to collect royalties through any statutory or 142 | compulsory licensing scheme cannot be waived, the Licensor 143 | reserves the exclusive right to collect such royalties for any 144 | exercise by You of the rights granted under this License; 145 | ii. Waivable Compulsory License Schemes. In those jurisdictions in 146 | which the right to collect royalties through any statutory or 147 | compulsory licensing scheme can be waived, the Licensor waives the 148 | exclusive right to collect such royalties for any exercise by You 149 | of the rights granted under this License; and, 150 | iii. Voluntary License Schemes. The Licensor waives the right to 151 | collect royalties, whether individually or, in the event that the 152 | Licensor is a member of a collecting society that administers 153 | voluntary licensing schemes, via that society, from any exercise 154 | by You of the rights granted under this License. 155 | 156 | The above rights may be exercised in all media and formats whether now 157 | known or hereafter devised. The above rights include the right to make 158 | such modifications as are technically necessary to exercise the rights in 159 | other media and formats. Subject to Section 8(f), all rights not expressly 160 | granted by Licensor are hereby reserved. 161 | 162 | 4. Restrictions. The license granted in Section 3 above is expressly made 163 | subject to and limited by the following restrictions: 164 | 165 | a. You may Distribute or Publicly Perform the Work only under the terms 166 | of this License. You must include a copy of, or the Uniform Resource 167 | Identifier (URI) for, this License with every copy of the Work You 168 | Distribute or Publicly Perform. You may not offer or impose any terms 169 | on the Work that restrict the terms of this License or the ability of 170 | the recipient of the Work to exercise the rights granted to that 171 | recipient under the terms of the License. You may not sublicense the 172 | Work. You must keep intact all notices that refer to this License and 173 | to the disclaimer of warranties with every copy of the Work You 174 | Distribute or Publicly Perform. When You Distribute or Publicly 175 | Perform the Work, You may not impose any effective technological 176 | measures on the Work that restrict the ability of a recipient of the 177 | Work from You to exercise the rights granted to that recipient under 178 | the terms of the License. This Section 4(a) applies to the Work as 179 | incorporated in a Collection, but this does not require the Collection 180 | apart from the Work itself to be made subject to the terms of this 181 | License. If You create a Collection, upon notice from any Licensor You 182 | must, to the extent practicable, remove from the Collection any credit 183 | as required by Section 4(c), as requested. If You create an 184 | Adaptation, upon notice from any Licensor You must, to the extent 185 | practicable, remove from the Adaptation any credit as required by 186 | Section 4(c), as requested. 187 | b. You may Distribute or Publicly Perform an Adaptation only under the 188 | terms of: (i) this License; (ii) a later version of this License with 189 | the same License Elements as this License; (iii) a Creative Commons 190 | jurisdiction license (either this or a later license version) that 191 | contains the same License Elements as this License (e.g., 192 | Attribution-ShareAlike 3.0 US)); (iv) a Creative Commons Compatible 193 | License. If you license the Adaptation under one of the licenses 194 | mentioned in (iv), you must comply with the terms of that license. If 195 | you license the Adaptation under the terms of any of the licenses 196 | mentioned in (i), (ii) or (iii) (the "Applicable License"), you must 197 | comply with the terms of the Applicable License generally and the 198 | following provisions: (I) You must include a copy of, or the URI for, 199 | the Applicable License with every copy of each Adaptation You 200 | Distribute or Publicly Perform; (II) You may not offer or impose any 201 | terms on the Adaptation that restrict the terms of the Applicable 202 | License or the ability of the recipient of the Adaptation to exercise 203 | the rights granted to that recipient under the terms of the Applicable 204 | License; (III) You must keep intact all notices that refer to the 205 | Applicable License and to the disclaimer of warranties with every copy 206 | of the Work as included in the Adaptation You Distribute or Publicly 207 | Perform; (IV) when You Distribute or Publicly Perform the Adaptation, 208 | You may not impose any effective technological measures on the 209 | Adaptation that restrict the ability of a recipient of the Adaptation 210 | from You to exercise the rights granted to that recipient under the 211 | terms of the Applicable License. This Section 4(b) applies to the 212 | Adaptation as incorporated in a Collection, but this does not require 213 | the Collection apart from the Adaptation itself to be made subject to 214 | the terms of the Applicable License. 215 | c. If You Distribute, or Publicly Perform the Work or any Adaptations or 216 | Collections, You must, unless a request has been made pursuant to 217 | Section 4(a), keep intact all copyright notices for the Work and 218 | provide, reasonable to the medium or means You are utilizing: (i) the 219 | name of the Original Author (or pseudonym, if applicable) if supplied, 220 | and/or if the Original Author and/or Licensor designate another party 221 | or parties (e.g., a sponsor institute, publishing entity, journal) for 222 | attribution ("Attribution Parties") in Licensor's copyright notice, 223 | terms of service or by other reasonable means, the name of such party 224 | or parties; (ii) the title of the Work if supplied; (iii) to the 225 | extent reasonably practicable, the URI, if any, that Licensor 226 | specifies to be associated with the Work, unless such URI does not 227 | refer to the copyright notice or licensing information for the Work; 228 | and (iv) , consistent with Ssection 3(b), in the case of an 229 | Adaptation, a credit identifying the use of the Work in the Adaptation 230 | (e.g., "French translation of the Work by Original Author," or 231 | "Screenplay based on original Work by Original Author"). The credit 232 | required by this Section 4(c) may be implemented in any reasonable 233 | manner; provided, however, that in the case of a Adaptation or 234 | Collection, at a minimum such credit will appear, if a credit for all 235 | contributing authors of the Adaptation or Collection appears, then as 236 | part of these credits and in a manner at least as prominent as the 237 | credits for the other contributing authors. For the avoidance of 238 | doubt, You may only use the credit required by this Section for the 239 | purpose of attribution in the manner set out above and, by exercising 240 | Your rights under this License, You may not implicitly or explicitly 241 | assert or imply any connection with, sponsorship or endorsement by the 242 | Original Author, Licensor and/or Attribution Parties, as appropriate, 243 | of You or Your use of the Work, without the separate, express prior 244 | written permission of the Original Author, Licensor and/or Attribution 245 | Parties. 246 | d. Except as otherwise agreed in writing by the Licensor or as may be 247 | otherwise permitted by applicable law, if You Reproduce, Distribute or 248 | Publicly Perform the Work either by itself or as part of any 249 | Adaptations or Collections, You must not distort, mutilate, modify or 250 | take other derogatory action in relation to the Work which would be 251 | prejudicial to the Original Author's honor or reputation. Licensor 252 | agrees that in those jurisdictions (e.g. Japan), in which any exercise 253 | of the right granted in Section 3(b) of this License (the right to 254 | make Adaptations) would be deemed to be a distortion, mutilation, 255 | modification or other derogatory action prejudicial to the Original 256 | Author's honor and reputation, the Licensor will waive or not assert, 257 | as appropriate, this Section, to the fullest extent permitted by the 258 | applicable national law, to enable You to reasonably exercise Your 259 | right under Section 3(b) of this License (right to make Adaptations) 260 | but not otherwise. 261 | 262 | 5. Representations, Warranties and Disclaimer 263 | 264 | UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR 265 | OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY 266 | KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, 267 | INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, 268 | FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF 269 | LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, 270 | WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION 271 | OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. 272 | 273 | 6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE 274 | LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR 275 | ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES 276 | ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS 277 | BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 278 | 279 | 7. Termination 280 | 281 | a. This License and the rights granted hereunder will terminate 282 | automatically upon any breach by You of the terms of this License. 283 | Individuals or entities who have received Adaptations or Collections 284 | from You under this License, however, will not have their licenses 285 | terminated provided such individuals or entities remain in full 286 | compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will 287 | survive any termination of this License. 288 | b. Subject to the above terms and conditions, the license granted here is 289 | perpetual (for the duration of the applicable copyright in the Work). 290 | Notwithstanding the above, Licensor reserves the right to release the 291 | Work under different license terms or to stop distributing the Work at 292 | any time; provided, however that any such election will not serve to 293 | withdraw this License (or any other license that has been, or is 294 | required to be, granted under the terms of this License), and this 295 | License will continue in full force and effect unless terminated as 296 | stated above. 297 | 298 | 8. Miscellaneous 299 | 300 | a. Each time You Distribute or Publicly Perform the Work or a Collection, 301 | the Licensor offers to the recipient a license to the Work on the same 302 | terms and conditions as the license granted to You under this License. 303 | b. Each time You Distribute or Publicly Perform an Adaptation, Licensor 304 | offers to the recipient a license to the original Work on the same 305 | terms and conditions as the license granted to You under this License. 306 | c. If any provision of this License is invalid or unenforceable under 307 | applicable law, it shall not affect the validity or enforceability of 308 | the remainder of the terms of this License, and without further action 309 | by the parties to this agreement, such provision shall be reformed to 310 | the minimum extent necessary to make such provision valid and 311 | enforceable. 312 | d. No term or provision of this License shall be deemed waived and no 313 | breach consented to unless such waiver or consent shall be in writing 314 | and signed by the party to be charged with such waiver or consent. 315 | e. This License constitutes the entire agreement between the parties with 316 | respect to the Work licensed here. There are no understandings, 317 | agreements or representations with respect to the Work not specified 318 | here. Licensor shall not be bound by any additional provisions that 319 | may appear in any communication from You. This License may not be 320 | modified without the mutual written agreement of the Licensor and You. 321 | f. The rights granted under, and the subject matter referenced, in this 322 | License were drafted utilizing the terminology of the Berne Convention 323 | for the Protection of Literary and Artistic Works (as amended on 324 | September 28, 1979), the Rome Convention of 1961, the WIPO Copyright 325 | Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 326 | and the Universal Copyright Convention (as revised on July 24, 1971). 327 | These rights and subject matter take effect in the relevant 328 | jurisdiction in which the License terms are sought to be enforced 329 | according to the corresponding provisions of the implementation of 330 | those treaty provisions in the applicable national law. If the 331 | standard suite of rights granted under applicable copyright law 332 | includes additional rights not granted under this License, such 333 | additional rights are deemed to be included in the License; this 334 | License is not intended to restrict the license of any rights under 335 | applicable law. 336 | 337 | 338 | Creative Commons Notice 339 | 340 | Creative Commons is not a party to this License, and makes no warranty 341 | whatsoever in connection with the Work. Creative Commons will not be 342 | liable to You or any party on any legal theory for any damages 343 | whatsoever, including without limitation any general, special, 344 | incidental or consequential damages arising in connection to this 345 | license. Notwithstanding the foregoing two (2) sentences, if Creative 346 | Commons has expressly identified itself as the Licensor hereunder, it 347 | shall have all rights and obligations of Licensor. 348 | 349 | Except for the limited purpose of indicating to the public that the 350 | Work is licensed under the CCPL, Creative Commons does not authorize 351 | the use by either party of the trademark "Creative Commons" or any 352 | related trademark or logo of Creative Commons without the prior 353 | written consent of Creative Commons. Any permitted use will be in 354 | compliance with Creative Commons' then-current trademark usage 355 | guidelines, as may be published on its website or otherwise made 356 | available upon request from time to time. For the avoidance of doubt, 357 | this trademark restriction does not form part of the License. 358 | 359 | Creative Commons may be contacted at https://creativecommons.org/. 360 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # openscad-documentation 2 | OpenSCAD offline documentation based on books published via Wikibooks 3 | 4 | --- 5 | [![Creative Commons License](https://i.creativecommons.org/l/by-sa/3.0/88x31.png)](http://creativecommons.org/licenses/by-sa/3.0/) - This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License](http://creativecommons.org/licenses/by-sa/3.0/). 6 | -------------------------------------------------------------------------------- /scripts/config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | url : https://en.wikibooks.org/wiki/OpenSCAD_User_Manual 3 | url_css : https://en.wikipedia.org/w/load.php?debug=false&lang=en&modules=mediawiki.legacy.commonPrint,shared|skins.vector.styles&only=styles&skin=vector&* 4 | url_wiki : https://en.wikibooks.org 5 | url_api : https://en.wikibooks.org/w/api.php?action=parse&format=xml&prop=text&page= 6 | 7 | pages_for_exclusion : [https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Example/Strandbeest] 8 | 9 | user_agent_val : Generator-for-Offline-Documentation (https://github.com/abshk-jr ; https://github.com/opencax/GSoC/issues/6 ; https://summerofcode.withgoogle.com/projects/#6746958066089984) urllib/3.9.0 [BeautifulSoup/4.9.0] 10 | 11 | url_print : [https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Print_version,https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language] 12 | 13 | cheatsheet_url : https://openscad.org/cheatsheet/ 14 | 15 | options : 16 | enable-local-file-access: null 17 | --keep-relative-links: '' -------------------------------------------------------------------------------- /scripts/offline-doc-generator.py: -------------------------------------------------------------------------------- 1 | ''' 2 | This is the code for `Generator for offline documentation`, more 3 | about which can be read at https://github.com/opencax/GSoC/issues/6 4 | and the GSOC project details for the same can be checked out at 5 | https://summerofcode.withgoogle.com/projects/#6746958066089984 6 | 7 | ''' 8 | import urllib.request, urllib.parse, os, yaml 9 | from bs4 import BeautifulSoup as bs,Comment, Doctype 10 | import shutil 11 | import pdfkit 12 | import platform 13 | if platform.system() == 'Linux': import cairosvg 14 | 15 | with open(os.path.join( os.path.dirname(__file__),'config.yml'),'r') as file: 16 | config = yaml.safe_load(file) 17 | 18 | #Update the global variables with the data from config.yml 19 | globals().update(config) 20 | 21 | dir_docs = 'openscad_docs' 22 | dir_imgs = os.path.join( dir_docs, 'imgs') 23 | dir_maths = os.path.join( dir_docs, 'imgs','maths') 24 | dir_styles = os.path.join( dir_docs, 'styles') 25 | 26 | #Create the directories to save the documentation 27 | if not os.path.exists(dir_docs): os.makedirs(dir_docs) 28 | if not os.path.exists(dir_imgs): os.makedirs(dir_imgs) 29 | if not os.path.exists(dir_maths): os.makedirs(dir_maths) 30 | if not os.path.exists(dir_styles): os.makedirs(dir_styles) 31 | 32 | dir_pdfs = 'openscad_docs_pdf' 33 | if not os.path.exists(dir_pdfs): os.makedirs(dir_pdfs) 34 | dir_docpdfs = 'docs_pdf' 35 | if not os.path.exists(dir_docpdfs): os.makedirs(dir_docpdfs) 36 | dir_pdfimgs = os.path.join( dir_pdfs, 'imgs') 37 | if not os.path.exists(dir_pdfimgs): os.makedirs(dir_pdfimgs) 38 | dir_pdfmaths = os.path.join( dir_pdfs, 'imgs', 'maths') 39 | if not os.path.exists(dir_pdfmaths): os.makedirs(dir_pdfmaths) 40 | 41 | pages =[] 42 | pages += pages_for_exclusion 43 | imgs =[] 44 | maths =[] 45 | 46 | def getParsedUrl(url): 47 | ''' 48 | This function generates a parsed url after accepting the url from the src inside the tags 49 | e.g. /wiki/OpenSCAD_User_Manual gets converted to https://en.wikibooks.org/wiki/OpenSCAD_User_Manual 50 | 51 | ''' 52 | if url.startswith('//'): 53 | url = 'https:'+url 54 | elif not url.startswith( url_wiki ): 55 | url = urllib.parse.urljoin( url_wiki, url[0]=="/" and url[1:] or url) 56 | return urllib.parse.urlparse(url) 57 | 58 | def getTags(soup,pdf,cs=False): 59 | ''' 60 | This function handles the different tags present in the HTML document 61 | e.x. updating the tags with the new links, or handling the tags 62 | 63 | ''' 64 | for a in soup.find_all('a'): 65 | href= a.get('href') 66 | if href: 67 | if href[0] != '#': 68 | if cs: 69 | href = href.replace('w/index.php?title=','wiki/') 70 | hrefparse = getParsedUrl(href) 71 | hrefurl=hrefparse.geturl() 72 | if pdf: 73 | a['href']= hrefurl 74 | elif hrefparse.path.startswith('/wiki/OpenSCAD_User_Manual'): 75 | newhref = (hrefurl.replace('#', '.html#') if '#' in hrefurl else hrefurl+'.html').split('/')[-1] 76 | 77 | if 'Print_version.html' not in newhref: 78 | if not cs: 79 | getPages(url=hrefurl) 80 | a['href']= newhref 81 | 82 | if a.img : 83 | getImages( a,pdf ) 84 | 85 | def getMaths(soup,pdf): 86 | ''' 87 | This function downloads the SVG files for the Math Formulas 88 | that are being used on various pages, for example at 89 | https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Mathematical_Operators 90 | and saves them to the directory /openscad_docs/imgs/maths 91 | 92 | ''' 93 | for img in soup.find_all('img'): 94 | try: 95 | for cls in img['class']: 96 | if('math' in cls): 97 | mathname = img['src'].split("/")[-1].split("\\")[-1] + '.svg' 98 | savepath = os.path.join( dir_maths, mathname) if not pdf else os.path.join( dir_pdfmaths, mathname) 99 | savepath_png = savepath.replace('.svg','.png') 100 | if (not mathname in maths) or pdf: 101 | opener = urllib.request.build_opener() 102 | opener.addheaders = [('User-Agent',user_agent_val)] 103 | urllib.request.install_opener(opener) 104 | urllib.request.urlretrieve( img['src'] , savepath ) 105 | if pdf and platform.system() == 'Linux': 106 | ''' 107 | This part of the code converts the SVGs to PNGs if the program is being run on Linux, 108 | to overcome the issue where WebKit Engine renders the SVG images at incorrrect sizing 109 | ''' 110 | cairosvg.svg2png(url=savepath, write_to=savepath_png) 111 | os.remove(savepath) 112 | maths.append( mathname ) 113 | if pdf and platform.system() == 'Linux': 114 | linkurl = os.path.join('.','imgs/maths',mathname).replace('\\','/').replace('.svg','.png') 115 | else: 116 | linkurl = os.path.join('.','imgs/maths',mathname).replace('\\','/') 117 | img['src'] = linkurl 118 | 119 | except: 120 | pass 121 | 122 | def getImages(tag,pdf): 123 | ''' 124 | This function downloads the images present in the HTML files 125 | and saves them to the directory - /openscad_docs/imgs 126 | 127 | ''' 128 | srcparse = getParsedUrl( tag.img['src'] ) 129 | imgname = srcparse.path.split("/")[-1] 130 | imgname = imgname.replace('%','_') 131 | imgpath = os.path.join( dir_imgs, imgname) if not pdf else os.path.join( dir_pdfimgs, imgname) 132 | 133 | #The following is to download the image if it hasn't alrady been downloaded 134 | if not imgpath in imgs: 135 | opener = urllib.request.build_opener() 136 | opener.addheaders = [('User-Agent',user_agent_val)] 137 | urllib.request.install_opener(opener) 138 | urllib.request.urlretrieve(srcparse.geturl() , imgpath) 139 | imgs.append(imgpath) 140 | 141 | del tag.img['srcset'] 142 | imgpath = os.path.join('.', 'imgs', imgname).replace('\\','/') 143 | tag.img['src'] = imgpath 144 | tag['href']= imgpath 145 | 146 | def cleanSoup(soup,pdf): 147 | ''' 148 | This function cleans the HTML by removing the redundant tags 149 | and the sections which are not necessary for the User Manual 150 | ''' 151 | 152 | #The following deletes the Tags which aren't required in the User Manual 153 | red_dict = {'div' : ["printfooter","catlinks","noprint","magnify"], 'table' : ['noprint'], 'input' : ['toctogglecheckbox']} 154 | for tag,cls_list in red_dict.items(): 155 | for cls in cls_list: 156 | for tag in soup.findAll(tag,{'class':cls}): 157 | tag.decompose() 158 | 159 | for tag in soup.findAll('table',{'class':'ambox'}): 160 | tag.decompose() 161 | 162 | for tag in soup.findAll('style'): 163 | tag.decompose() 164 | 165 | #The following removes the comments present in the HTML document 166 | comments = soup.findAll(text=lambda text: isinstance(text, Comment)) 167 | [comment.extract() for comment in comments] 168 | 169 | #The following replaces the redundant div Tags with the content present inside of them 170 | rep_div_cls = ["mw-highlight"] 171 | for kls in rep_div_cls: 172 | for tag in soup.findAll('div',kls): 173 | tag.replaceWithChildren() 174 | 175 | #The following removes the non-contributing classes in li tags 176 | for _ in range(0,7): 177 | for tag in soup.findAll('li',{'class':f'toclevel-{_}'}): 178 | del tag['class'] 179 | 180 | #The following is for the removal/cleaning of some redundant span tags 181 | for tag in soup.findAll('span'): 182 | try: 183 | if(len(tag.text)==0): 184 | tag.decompose() 185 | for cls in tag['class']: 186 | if(len(cls) <= 2): 187 | tag.replaceWithChildren() 188 | elif cls in ['toctext'] or (pdf and cls in ['tocnumber']): 189 | tag.replaceWithChildren() 190 | elif cls in ['mw-headline']: 191 | del tag['class'] 192 | elif 'mathml' in cls or cls in ['mw-editsection','toctogglespan','noprint']: 193 | tag.decompose() 194 | 195 | except: 196 | pass 197 | 198 | #The following is to replace the tabs in the code blocks with spaces 199 | for txt in soup.findAll('pre'): 200 | txt.string = txt.text.replace('\t',' ') 201 | if pdf: 202 | if platform.system() == 'Linux': 203 | for _ in soup.findAll('pre'): 204 | _['style']="font-family:'Liberation Mono'" 205 | 206 | #The following unwraps the tables in the pdfs for a better formatting 207 | if pdf: 208 | for table in soup.findAll('table'): 209 | for row in table.findAll('tr'): 210 | for col in row.findAll('td'): 211 | col.unwrap() 212 | row.unwrap() 213 | table.unwrap() 214 | 215 | for tag in soup.findAll('ul'): 216 | tag['style'] = 'list-style-image:none' 217 | 218 | 219 | def getFooter( url, name ): 220 | ''' 221 | This function generates the Footer containing the necessary license attribution 222 | 223 | ''' 224 | footer = (f'''''') 228 | 229 | return bs(footer,'html.parser') 230 | 231 | def getStyled(soup,title): 232 | tag = Doctype('html') 233 | soup.insert(0, tag) 234 | soup.html['lang']='en' 235 | meta_tag = soup.new_tag('meta') 236 | meta_tag['charset'] = 'UTF-8' 237 | soup.head.insert(0,meta_tag) 238 | css_tag = bs('','html.parser') 239 | soup.head.append(css_tag) 240 | soup.body['class'] = 'mw-body' 241 | soup.body['style']=['height:auto;background-color:#ffffff'] 242 | del soup.body.div['class'] 243 | soup.body.div['id']='bodyContent' 244 | h1_tag = bs(f'

{title}

','html.parser') 245 | soup.body.insert(0,h1_tag) 246 | 247 | def getPages( url=url,folder=dir_docs,pdf=False ): 248 | ''' 249 | This is the main function of the program 250 | which downloads the webpage at the given url 251 | and calls different functions to generate the Offline 252 | version of the page and save it under the directory /openscad_docs 253 | 254 | ''' 255 | if url.split("#")[0] not in pages or pdf: 256 | pages.append( url.split("#")[0] ) #adds the url to the `pages` list so that the page doesn't get downloaded again 257 | wiki_url = url 258 | url = url.replace(url_wiki+'/wiki/', "") 259 | url = url_api + url 260 | 261 | request = urllib.request.Request(url) 262 | request.add_header('User-Agent',user_agent_val) 263 | response = urllib.request.urlopen(request) 264 | xml = response.read() 265 | soup = bs(xml, 'html.parser') 266 | soup = soup.text 267 | soup = bs(soup,'html5lib') 268 | 269 | name = url.split("=")[-1] 270 | name = name.split("/")[-1].split('#')[0] #converts OpenSCAD_User_Manual/String_Functions#str to String_Functions 271 | 272 | if pdf==True: name = 'OpenSCAD_User_Manual' if (name == 'Print_version') else name 273 | 274 | title = soup.new_tag("title") #adds title to the pages 275 | title.string = name.replace("_" , " ") 276 | soup.html.head.append(title) 277 | 278 | name = name + ".html" 279 | filepath = os.path.join( folder, name) 280 | 281 | print("Saving: ", filepath) 282 | 283 | getStyled(soup,title.string) 284 | cleanSoup(soup,pdf) 285 | getMaths(soup,pdf) 286 | getTags(soup,pdf,False) 287 | 288 | soup.body.append( getFooter( wiki_url, title.text )) 289 | 290 | open(filepath, "w", encoding="utf-8").write( str(soup) ) 291 | 292 | 293 | def getCSS(url = url_css, css_name = 'style.css'): 294 | ''' 295 | This function runs once after the HTML files have been downloaded 296 | and downloads the CSS given at https://www.mediawiki.org/wiki/API:Styling_content 297 | and saves it to openscad_docs/styles 298 | 299 | ''' 300 | request = urllib.request.Request(url) 301 | request.add_header('User-Agent',user_agent_val) 302 | response = urllib.request.urlopen(request) 303 | css_soup = response.read() 304 | css = bs(css_soup, 'html5lib') 305 | csspath = os.path.join( dir_styles, css_name) 306 | open( csspath, "w" , encoding="utf-8").write(css.body.text) 307 | 308 | def getPdf(): 309 | for link in url_print: 310 | getPages(link,folder=dir_pdfs,pdf=True) 311 | if os.path.exists(f'{os.path.join( os.getcwd(), dir_pdfs)}/styles'):shutil.rmtree(f'{os.path.join( os.getcwd(), dir_pdfs)}/styles') 312 | shutil.copytree(f'{os.path.join( os.getcwd(), dir_docs)}/styles', f'{os.path.join( os.getcwd(), dir_pdfs)}/styles') 313 | 314 | def cheatSheet(): 315 | ''' 316 | This function is run once to download the Cheat Sheet from 317 | https://openscad.org/cheatsheet/ and the WikiBooks links 318 | are changed to now redirect to the Manual saved offline 319 | 320 | ''' 321 | request = urllib.request.Request(cheatsheet_url) 322 | response = urllib.request.urlopen(request) 323 | soup = response.read() 324 | soup = bs(soup,'lxml') 325 | for css in soup.find_all("link",href=True): 326 | css_name = css.attrs.get("href") 327 | url_css = urllib.parse.urljoin(cheatsheet_url, css_name) 328 | if '.css' in url_css: 329 | getCSS(url_css,css_name.split('/')[-1]) 330 | css['href'] = css['href'].replace('css/','styles/') 331 | getTags(soup,False,True) 332 | filepath = os.path.join( dir_docs , 'CheatSheet.html') 333 | open(filepath, "w", encoding="utf-8").write( str(soup) ) 334 | 335 | 336 | 337 | if(__name__ == '__main__'): 338 | print(f'Started Offline Generator.py\nNow downloading the User-Manual from {url}') 339 | getPages(url) 340 | getCSS() 341 | print("Total number of pages generated is \t:\t", len(pages)-len(pages_for_exclusion)) 342 | print("Total number of images generated is \t:\t", len(imgs)) 343 | print("Total number of math-images generated is:\t", len(maths)) 344 | cheatSheet() 345 | shutil.make_archive('Generated-Offline-Manual', 'zip', dir_docs) 346 | 347 | getPdf() 348 | files=os.listdir(os.path.join( os.getcwd(), dir_pdfs)) 349 | for file in files: 350 | if ".html" in file: 351 | file_pdf = file.replace('.html','.pdf') 352 | pdfkit.from_file(f'{os.path.join( os.getcwd(), dir_pdfs)}/{file}', f'{os.path.join( os.getcwd(), dir_docpdfs)}/{file_pdf}' , options=options) 353 | 354 | shutil.make_archive('PDF-Offline-Manual', 'zip', dir_docpdfs) 355 | shutil.rmtree(dir_pdfs) 356 | shutil.rmtree(dir_docpdfs) -------------------------------------------------------------------------------- /scripts/requirements.txt: -------------------------------------------------------------------------------- 1 | beautifulsoup4==4.9.3 2 | PyYAML==5.4.1 3 | lxml==4.6.3 4 | html5lib==1.1 5 | pdfkit==0.6.1 6 | CairoSVG==2.5.2 --------------------------------------------------------------------------------