Repository: jandecaluwe/urubu Branch: master Commit: b4a9c533ed26 Files: 273 Total size: 1.3 MB Directory structure: gitextract_m28odmw2/ ├── .gitignore ├── LICENSE.txt ├── MANIFEST.in ├── README.md ├── doc/ │ ├── .nojekyll │ ├── CNAME │ ├── Makefile │ ├── _build/ │ │ ├── .nojekyll │ │ ├── CNAME │ │ ├── css/ │ │ │ ├── bootstrap.css │ │ │ ├── site.css │ │ │ └── syntax.css │ │ ├── faq/ │ │ │ ├── baseurl-preview.html │ │ │ ├── formulas.html │ │ │ ├── index.html │ │ │ ├── licensing-requirements.html │ │ │ ├── link2section.html │ │ │ ├── media-files.html │ │ │ ├── sitemap.html │ │ │ └── tags.html │ │ ├── index.html │ │ ├── js/ │ │ │ └── bootstrap.js │ │ ├── manual/ │ │ │ ├── alt_layouts.html │ │ │ ├── authoring.html │ │ │ ├── building.html │ │ │ ├── extensions.html │ │ │ ├── hooks.html │ │ │ ├── index.html │ │ │ ├── install.html │ │ │ ├── intro.html │ │ │ ├── pagination.html │ │ │ ├── search.html │ │ │ ├── structure.html │ │ │ ├── templates.html │ │ │ └── templating-in-pages.html │ │ ├── more/ │ │ │ ├── about.html │ │ │ ├── index.html │ │ │ └── sites.html │ │ ├── news/ │ │ │ ├── 2014-01-12.html │ │ │ ├── 2014-01-22.html │ │ │ ├── 2014-02-15.html │ │ │ ├── 2014-02-27.html │ │ │ ├── 2014-03-18.html │ │ │ ├── 2014-05-25.html │ │ │ ├── 2014-09-08.html │ │ │ ├── 2015-01-28.html │ │ │ ├── 2015-03-07.html │ │ │ ├── 2015-11-22.html │ │ │ ├── 2015-12-15.html │ │ │ ├── 2016-01-01.html │ │ │ ├── 2016-01-10.html │ │ │ ├── 2016-02-12.html │ │ │ ├── 2016-11-14.html │ │ │ ├── 2018-08-15.html │ │ │ ├── 2024-12-30.html │ │ │ ├── 2026-03-30.html │ │ │ └── index.html │ │ ├── search.html │ │ ├── start.html │ │ └── tipuesearch/ │ │ ├── tipuesearch.css │ │ ├── tipuesearch.css.in │ │ ├── tipuesearch.js │ │ ├── tipuesearch_content.js │ │ ├── tipuesearch_content.json │ │ └── tipuesearch_set.js │ ├── _layouts/ │ │ ├── _base.html │ │ ├── analytics.html │ │ ├── footer.html │ │ ├── home.html │ │ ├── index.html │ │ ├── newsfeed.html │ │ ├── page.html │ │ ├── search.html │ │ ├── sharing.html │ │ ├── simple_page.html │ │ └── util.html │ ├── _python/ │ │ ├── __init__.py │ │ ├── filters.py │ │ └── hooks.py │ ├── _site.yml │ ├── css/ │ │ ├── bootstrap.css │ │ ├── site.css │ │ └── syntax.css │ ├── faq/ │ │ ├── baseurl-preview.md │ │ ├── formulas.md │ │ ├── index.md │ │ ├── licensing-requirements.md │ │ ├── link2section.md │ │ ├── media-files.md │ │ ├── sitemap.md │ │ └── tags.md │ ├── index.md │ ├── js/ │ │ └── bootstrap.js │ ├── manual/ │ │ ├── alt_layouts.md │ │ ├── authoring.md │ │ ├── building.md │ │ ├── extensions.md │ │ ├── hooks.md │ │ ├── index.md │ │ ├── install.md │ │ ├── intro.md │ │ ├── pagination.md │ │ ├── search.md │ │ ├── structure.md │ │ ├── templates.md │ │ └── templating-in-pages.md │ ├── more/ │ │ ├── about.md │ │ ├── index.md │ │ └── sites.md │ ├── news/ │ │ ├── 2014-01-12.md │ │ ├── 2014-01-22.md │ │ ├── 2014-02-15.md │ │ ├── 2014-02-27.md │ │ ├── 2014-03-18.md │ │ ├── 2014-05-25.md │ │ ├── 2014-09-08.md │ │ ├── 2015-01-28.md │ │ ├── 2015-03-07.md │ │ ├── 2015-11-22.md │ │ ├── 2015-12-15.md │ │ ├── 2016-01-01.md │ │ ├── 2016-01-10.md │ │ ├── 2016-02-12.md │ │ ├── 2016-11-14.md │ │ ├── 2018-08-15.md │ │ ├── 2024-12-30.md │ │ ├── 2026-03-30.md │ │ └── index.md │ ├── search.md │ ├── start.md │ └── tipuesearch/ │ ├── tipuesearch.css │ ├── tipuesearch.css.in │ ├── tipuesearch.js │ ├── tipuesearch_content.js │ └── tipuesearch_set.js ├── setup.py ├── tox.ini └── urubu/ ├── __init__.py ├── __main__.py ├── config.py ├── httphandler.py ├── main.py ├── md_extensions.py ├── processors.py ├── project.py ├── readers.py └── tests/ ├── __init__.py ├── ambig_ref/ │ ├── _build/ │ │ ├── github.html │ │ ├── index.html │ │ └── page.html │ ├── _layouts/ │ │ ├── _base.html │ │ └── page.html │ ├── _site.yml │ ├── github.md │ ├── index.md │ └── page.md ├── ambig_ref_md/ │ ├── _layouts/ │ │ ├── _base.html │ │ └── page.html │ ├── _site.yml │ ├── github.md │ ├── index.md │ └── page.md ├── ambig_refid/ │ ├── _build/ │ │ ├── index.html │ │ └── page.html │ ├── _layouts/ │ │ ├── _base.html │ │ └── page.html │ ├── _site.yml │ ├── index.md │ ├── page/ │ │ └── index.md │ └── page.md ├── date_format/ │ ├── _build/ │ │ ├── index.html │ │ └── page.html │ ├── _layouts/ │ │ ├── _base.html │ │ └── page.html │ ├── _site.yml │ ├── index.md │ └── page.md ├── ignore_patterns/ │ ├── README.md │ ├── _build/ │ │ ├── index.html │ │ └── page.html │ ├── _layouts/ │ │ ├── _base.html │ │ └── page.html │ ├── _site.yml │ ├── index.md │ └── page.md ├── no_index/ │ ├── _build/ │ │ ├── index.html │ │ └── page.html │ ├── _layouts/ │ │ ├── _base.html │ │ └── page.html │ ├── _site.yml │ ├── folder/ │ │ └── page.md │ ├── index.md │ └── page.md ├── no_yamlfm/ │ ├── _build/ │ │ └── index.html │ ├── _layouts/ │ │ ├── _base.html │ │ └── page.html │ ├── _site.yml │ ├── index.md │ └── page.md ├── test_doc.py ├── test_errors.py ├── test_warnings.py ├── undef_anchor/ │ ├── _build/ │ │ ├── index.html │ │ ├── page.html │ │ └── page2.html │ ├── _layouts/ │ │ ├── _base.html │ │ └── page.html │ ├── _site.yml │ ├── index.md │ ├── page.md │ └── page2.md ├── undef_content/ │ ├── _build/ │ │ ├── index.html │ │ └── page.html │ ├── _layouts/ │ │ ├── _base.html │ │ └── page.html │ ├── _site.yml │ ├── index.md │ └── page.md ├── undef_key/ │ ├── _build/ │ │ ├── folder/ │ │ │ ├── index.html │ │ │ └── item.d │ │ ├── index.html │ │ └── page.html │ ├── _layouts/ │ │ ├── _base.html │ │ └── page.html │ ├── _site.yml │ ├── folder/ │ │ ├── index.md │ │ └── item.md │ ├── index.md │ └── page.md ├── undef_layout/ │ ├── _build/ │ │ ├── index.html │ │ └── page.html │ ├── _layouts/ │ │ ├── _base.html │ │ └── page.html │ ├── _site.yml │ ├── index.md │ └── page.md ├── undef_ref/ │ ├── _build/ │ │ ├── index.html │ │ └── page.html │ ├── _layouts/ │ │ ├── _base.html │ │ └── page.html │ ├── _site.yml │ ├── index.md │ └── page.md ├── undef_ref_md/ │ ├── _build/ │ │ ├── index.html │ │ ├── page.html │ │ └── page2.html │ ├── _layouts/ │ │ ├── _base.html │ │ └── page.html │ ├── _site.yml │ ├── index.md │ ├── page.md │ └── page2.md ├── undef_reflink_title/ │ ├── _build/ │ │ ├── index.html │ │ └── page.html │ ├── _layouts/ │ │ ├── _base.html │ │ └── page.html │ ├── _site.yml │ ├── index.md │ └── page.md ├── undef_reflink_url/ │ ├── _build/ │ │ ├── index.html │ │ └── page.html │ ├── _layouts/ │ │ ├── _base.html │ │ └── page.html │ ├── _site.yml │ ├── index.md │ └── page.md └── undef_tag_layout/ ├── _build/ │ ├── index.html │ └── page.html ├── _layouts/ │ ├── _base.html │ └── page.html ├── _site.yml ├── index.md └── page.md ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] # C extensions *.so # Distribution / packaging .Python env/ build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ *.egg-info/ .installed.cfg *.egg # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .coverage .coverage.* .cache nosetests.xml coverage.xml # Translations *.mo *.pot # Django stuff: *.log # Sphinx documentation docs/_build/ # PyBuilder target/ *~ *.bak ================================================ FILE: LICENSE.txt ================================================ GNU AFFERO GENERAL PUBLIC LICENSE Version 3, 19 November 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU Affero General Public License is a free, copyleft license for software and other kinds of works, specifically designed to ensure cooperation with the community in the case of network server software. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, our General Public Licenses are 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. 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. Developers that use our General Public Licenses protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License which gives you legal permission to copy, distribute and/or modify the software. A secondary benefit of defending all users' freedom is that improvements made in alternate versions of the program, if they receive widespread use, become available for other developers to incorporate. Many developers of free software are heartened and encouraged by the resulting cooperation. However, in the case of software used on network servers, this result may fail to come about. The GNU General Public License permits making a modified version and letting the public access it on a server without ever releasing its source code to the public. The GNU Affero General Public License is designed specifically to ensure that, in such cases, the modified source code becomes available to the community. It requires the operator of a network server to provide the source code of the modified version running there to the users of that server. Therefore, public use of a modified version, on a publicly accessible server, gives the public access to the source code of the modified version. An older license, called the Affero General Public License and published by Affero, was designed to accomplish similar goals. This is a different license, not a version of the Affero GPL, but Affero has released a new version of the Affero GPL which permits relicensing under this license. 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 Affero 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. Remote Network Interaction; Use with the GNU General Public License. Notwithstanding any other provision of this License, if you modify the Program, your modified version must prominently offer all users interacting with it remotely through a computer network (if your version supports such interaction) an opportunity to receive the Corresponding Source of your version by providing access to the Corresponding Source from a network server at no charge, through some standard or customary means of facilitating copying of software. This Corresponding Source shall include the Corresponding Source for any work covered by version 3 of the GNU General Public License that is incorporated pursuant to the following paragraph. 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 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 work with which it is combined will remain governed by version 3 of the GNU General Public License. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU Affero 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 Affero 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 Affero 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 Affero 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. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If your software can interact with users remotely through a computer network, you should also make sure that it provides a way for users to get its source. For example, if your program is a web application, its interface could display a "Source" link that leads users to an archive of the code. There are many ways you could offer source, and different solutions will be better for different programs; see section 13 for the specific requirements. 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 AGPL, see . ================================================ FILE: MANIFEST.in ================================================ include *.txt include *.md graft doc prune doc/_build global-exclude *.pyc ================================================ FILE: README.md ================================================ Urubu 1.4.1 =========== Urubu is a micro CMS for static websites, with a focus on good navigation practices. All info can be found on the website: https://urubu.jandecaluwe.com ================================================ FILE: doc/.nojekyll ================================================ ================================================ FILE: doc/CNAME ================================================ urubu.jandecaluwe.com ================================================ FILE: doc/Makefile ================================================ GH-PAGES = ${HOME}/dev/urubu-gh-pages/ all: build build: python3 -m urubu build serve: python3 -m urubu serve publish: cd ..; git subtree push --prefix doc/_build origin gh-pages ================================================ FILE: doc/_build/.nojekyll ================================================ ================================================ FILE: doc/_build/CNAME ================================================ urubu.jandecaluwe.com ================================================ FILE: doc/_build/css/bootstrap.css ================================================ /*! * Bootstrap v3.4.1 (https://getbootstrap.com/) * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ /*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ html { font-family: sans-serif; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; } body { margin: 0; } article, aside, details, figcaption, figure, footer, header, hgroup, main, menu, nav, section, summary { display: block; } audio, canvas, progress, video { display: inline-block; vertical-align: baseline; } audio:not([controls]) { display: none; height: 0; } [hidden], template { display: none; } a { background-color: transparent; } a:active, a:hover { outline: 0; } abbr[title] { border-bottom: none; text-decoration: underline; -webkit-text-decoration: underline dotted; -moz-text-decoration: underline dotted; text-decoration: underline dotted; } b, strong { font-weight: bold; } dfn { font-style: italic; } h1 { font-size: 2em; margin: 0.67em 0; } mark { background: #ff0; color: #000; } small { font-size: 80%; } sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } sup { top: -0.5em; } sub { bottom: -0.25em; } img { border: 0; } svg:not(:root) { overflow: hidden; } figure { margin: 1em 40px; } hr { -webkit-box-sizing: content-box; -moz-box-sizing: content-box; box-sizing: content-box; height: 0; } pre { overflow: auto; } code, kbd, pre, samp { font-family: monospace, monospace; font-size: 1em; } button, input, optgroup, select, textarea { color: inherit; font: inherit; margin: 0; } button { overflow: visible; } button, select { text-transform: none; } button, html input[type="button"], input[type="reset"], input[type="submit"] { -webkit-appearance: button; cursor: pointer; } button[disabled], html input[disabled] { cursor: default; } button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; } input { line-height: normal; } input[type="checkbox"], input[type="radio"] { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; padding: 0; } input[type="number"]::-webkit-inner-spin-button, input[type="number"]::-webkit-outer-spin-button { height: auto; } input[type="search"] { -webkit-appearance: textfield; -webkit-box-sizing: content-box; -moz-box-sizing: content-box; box-sizing: content-box; } input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; } fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; } legend { border: 0; padding: 0; } textarea { overflow: auto; } optgroup { font-weight: bold; } table { border-collapse: collapse; border-spacing: 0; } td, th { padding: 0; } /*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ @media print { *, *:before, *:after { color: #000 !important; text-shadow: none !important; background: transparent !important; -webkit-box-shadow: none !important; box-shadow: none !important; } a, a:visited { text-decoration: underline; } a[href]:after { content: " (" attr(href) ")"; } abbr[title]:after { content: " (" attr(title) ")"; } a[href^="#"]:after, a[href^="javascript:"]:after { content: ""; } pre, blockquote { border: 1px solid #999; page-break-inside: avoid; } thead { display: table-header-group; } tr, img { page-break-inside: avoid; } img { max-width: 100% !important; } p, h2, h3 { orphans: 3; widows: 3; } h2, h3 { page-break-after: avoid; } .navbar { display: none; } .btn > .caret, .dropup > .btn > .caret { border-top-color: #000 !important; } .label { border: 1px solid #000; } .table { border-collapse: collapse !important; } .table td, .table th { background-color: #fff !important; } .table-bordered th, .table-bordered td { border: 1px solid #ddd !important; } } @font-face { font-family: "Glyphicons Halflings"; src: url("../fonts/glyphicons-halflings-regular.eot"); src: url("../fonts/glyphicons-halflings-regular.eot?#iefix") format("embedded-opentype"), url("../fonts/glyphicons-halflings-regular.woff2") format("woff2"), url("../fonts/glyphicons-halflings-regular.woff") format("woff"), url("../fonts/glyphicons-halflings-regular.ttf") format("truetype"), url("../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular") format("svg"); } .glyphicon { position: relative; top: 1px; display: inline-block; font-family: "Glyphicons Halflings"; font-style: normal; font-weight: 400; line-height: 1; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } .glyphicon-asterisk:before { content: "\002a"; } .glyphicon-plus:before { content: "\002b"; } .glyphicon-euro:before, .glyphicon-eur:before { content: "\20ac"; } .glyphicon-minus:before { content: "\2212"; } .glyphicon-cloud:before { content: "\2601"; } .glyphicon-envelope:before { content: "\2709"; } .glyphicon-pencil:before { content: "\270f"; } .glyphicon-glass:before { content: "\e001"; } .glyphicon-music:before { content: "\e002"; } .glyphicon-search:before { content: "\e003"; } .glyphicon-heart:before { content: "\e005"; } .glyphicon-star:before { content: "\e006"; } .glyphicon-star-empty:before { content: "\e007"; } .glyphicon-user:before { content: "\e008"; } .glyphicon-film:before { content: "\e009"; } .glyphicon-th-large:before { content: "\e010"; } .glyphicon-th:before { content: "\e011"; } .glyphicon-th-list:before { content: "\e012"; } .glyphicon-ok:before { content: "\e013"; } .glyphicon-remove:before { content: "\e014"; } .glyphicon-zoom-in:before { content: "\e015"; } .glyphicon-zoom-out:before { content: "\e016"; } .glyphicon-off:before { content: "\e017"; } .glyphicon-signal:before { content: "\e018"; } .glyphicon-cog:before { content: "\e019"; } .glyphicon-trash:before { content: "\e020"; } .glyphicon-home:before { content: "\e021"; } .glyphicon-file:before { content: "\e022"; } .glyphicon-time:before { content: "\e023"; } .glyphicon-road:before { content: "\e024"; } .glyphicon-download-alt:before { content: "\e025"; } .glyphicon-download:before { content: "\e026"; } .glyphicon-upload:before { content: "\e027"; } .glyphicon-inbox:before { content: "\e028"; } .glyphicon-play-circle:before { content: "\e029"; } .glyphicon-repeat:before { content: "\e030"; } .glyphicon-refresh:before { content: "\e031"; } .glyphicon-list-alt:before { content: "\e032"; } .glyphicon-lock:before { content: "\e033"; } .glyphicon-flag:before { content: "\e034"; } .glyphicon-headphones:before { content: "\e035"; } .glyphicon-volume-off:before { content: "\e036"; } .glyphicon-volume-down:before { content: "\e037"; } .glyphicon-volume-up:before { content: "\e038"; } .glyphicon-qrcode:before { content: "\e039"; } .glyphicon-barcode:before { content: "\e040"; } .glyphicon-tag:before { content: "\e041"; } .glyphicon-tags:before { content: "\e042"; } .glyphicon-book:before { content: "\e043"; } .glyphicon-bookmark:before { content: "\e044"; } .glyphicon-print:before { content: "\e045"; } .glyphicon-camera:before { content: "\e046"; } .glyphicon-font:before { content: "\e047"; } .glyphicon-bold:before { content: "\e048"; } .glyphicon-italic:before { content: "\e049"; } .glyphicon-text-height:before { content: "\e050"; } .glyphicon-text-width:before { content: "\e051"; } .glyphicon-align-left:before { content: "\e052"; } .glyphicon-align-center:before { content: "\e053"; } .glyphicon-align-right:before { content: "\e054"; } .glyphicon-align-justify:before { content: "\e055"; } .glyphicon-list:before { content: "\e056"; } .glyphicon-indent-left:before { content: "\e057"; } .glyphicon-indent-right:before { content: "\e058"; } .glyphicon-facetime-video:before { content: "\e059"; } .glyphicon-picture:before { content: "\e060"; } .glyphicon-map-marker:before { content: "\e062"; } .glyphicon-adjust:before { content: "\e063"; } .glyphicon-tint:before { content: "\e064"; } .glyphicon-edit:before { content: "\e065"; } .glyphicon-share:before { content: "\e066"; } .glyphicon-check:before { content: "\e067"; } .glyphicon-move:before { content: "\e068"; } .glyphicon-step-backward:before { content: "\e069"; } .glyphicon-fast-backward:before { content: "\e070"; } .glyphicon-backward:before { content: "\e071"; } .glyphicon-play:before { content: "\e072"; } .glyphicon-pause:before { content: "\e073"; } .glyphicon-stop:before { content: "\e074"; } .glyphicon-forward:before { content: "\e075"; } .glyphicon-fast-forward:before { content: "\e076"; } .glyphicon-step-forward:before { content: "\e077"; } .glyphicon-eject:before { content: "\e078"; } .glyphicon-chevron-left:before { content: "\e079"; } .glyphicon-chevron-right:before { content: "\e080"; } .glyphicon-plus-sign:before { content: "\e081"; } .glyphicon-minus-sign:before { content: "\e082"; } .glyphicon-remove-sign:before { content: "\e083"; } .glyphicon-ok-sign:before { content: "\e084"; } .glyphicon-question-sign:before { content: "\e085"; } .glyphicon-info-sign:before { content: "\e086"; } .glyphicon-screenshot:before { content: "\e087"; } .glyphicon-remove-circle:before { content: "\e088"; } .glyphicon-ok-circle:before { content: "\e089"; } .glyphicon-ban-circle:before { content: "\e090"; } .glyphicon-arrow-left:before { content: "\e091"; } .glyphicon-arrow-right:before { content: "\e092"; } .glyphicon-arrow-up:before { content: "\e093"; } .glyphicon-arrow-down:before { content: "\e094"; } .glyphicon-share-alt:before { content: "\e095"; } .glyphicon-resize-full:before { content: "\e096"; } .glyphicon-resize-small:before { content: "\e097"; } .glyphicon-exclamation-sign:before { content: "\e101"; } .glyphicon-gift:before { content: "\e102"; } .glyphicon-leaf:before { content: "\e103"; } .glyphicon-fire:before { content: "\e104"; } .glyphicon-eye-open:before { content: "\e105"; } .glyphicon-eye-close:before { content: "\e106"; } .glyphicon-warning-sign:before { content: "\e107"; } .glyphicon-plane:before { content: "\e108"; } .glyphicon-calendar:before { content: "\e109"; } .glyphicon-random:before { content: "\e110"; } .glyphicon-comment:before { content: "\e111"; } .glyphicon-magnet:before { content: "\e112"; } .glyphicon-chevron-up:before { content: "\e113"; } .glyphicon-chevron-down:before { content: "\e114"; } .glyphicon-retweet:before { content: "\e115"; } .glyphicon-shopping-cart:before { content: "\e116"; } .glyphicon-folder-close:before { content: "\e117"; } .glyphicon-folder-open:before { content: "\e118"; } .glyphicon-resize-vertical:before { content: "\e119"; } .glyphicon-resize-horizontal:before { content: "\e120"; } .glyphicon-hdd:before { content: "\e121"; } .glyphicon-bullhorn:before { content: "\e122"; } .glyphicon-bell:before { content: "\e123"; } .glyphicon-certificate:before { content: "\e124"; } .glyphicon-thumbs-up:before { content: "\e125"; } .glyphicon-thumbs-down:before { content: "\e126"; } .glyphicon-hand-right:before { content: "\e127"; } .glyphicon-hand-left:before { content: "\e128"; } .glyphicon-hand-up:before { content: "\e129"; } .glyphicon-hand-down:before { content: "\e130"; } .glyphicon-circle-arrow-right:before { content: "\e131"; } .glyphicon-circle-arrow-left:before { content: "\e132"; } .glyphicon-circle-arrow-up:before { content: "\e133"; } .glyphicon-circle-arrow-down:before { content: "\e134"; } .glyphicon-globe:before { content: "\e135"; } .glyphicon-wrench:before { content: "\e136"; } .glyphicon-tasks:before { content: "\e137"; } .glyphicon-filter:before { content: "\e138"; } .glyphicon-briefcase:before { content: "\e139"; } .glyphicon-fullscreen:before { content: "\e140"; } .glyphicon-dashboard:before { content: "\e141"; } .glyphicon-paperclip:before { content: "\e142"; } .glyphicon-heart-empty:before { content: "\e143"; } .glyphicon-link:before { content: "\e144"; } .glyphicon-phone:before { content: "\e145"; } .glyphicon-pushpin:before { content: "\e146"; } .glyphicon-usd:before { content: "\e148"; } .glyphicon-gbp:before { content: "\e149"; } .glyphicon-sort:before { content: "\e150"; } .glyphicon-sort-by-alphabet:before { content: "\e151"; } .glyphicon-sort-by-alphabet-alt:before { content: "\e152"; } .glyphicon-sort-by-order:before { content: "\e153"; } .glyphicon-sort-by-order-alt:before { content: "\e154"; } .glyphicon-sort-by-attributes:before { content: "\e155"; } .glyphicon-sort-by-attributes-alt:before { content: "\e156"; } .glyphicon-unchecked:before { content: "\e157"; } .glyphicon-expand:before { content: "\e158"; } .glyphicon-collapse-down:before { content: "\e159"; } .glyphicon-collapse-up:before { content: "\e160"; } .glyphicon-log-in:before { content: "\e161"; } .glyphicon-flash:before { content: "\e162"; } .glyphicon-log-out:before { content: "\e163"; } .glyphicon-new-window:before { content: "\e164"; } .glyphicon-record:before { content: "\e165"; } .glyphicon-save:before { content: "\e166"; } .glyphicon-open:before { content: "\e167"; } .glyphicon-saved:before { content: "\e168"; } .glyphicon-import:before { content: "\e169"; } .glyphicon-export:before { content: "\e170"; } .glyphicon-send:before { content: "\e171"; } .glyphicon-floppy-disk:before { content: "\e172"; } .glyphicon-floppy-saved:before { content: "\e173"; } .glyphicon-floppy-remove:before { content: "\e174"; } .glyphicon-floppy-save:before { content: "\e175"; } .glyphicon-floppy-open:before { content: "\e176"; } .glyphicon-credit-card:before { content: "\e177"; } .glyphicon-transfer:before { content: "\e178"; } .glyphicon-cutlery:before { content: "\e179"; } .glyphicon-header:before { content: "\e180"; } .glyphicon-compressed:before { content: "\e181"; } .glyphicon-earphone:before { content: "\e182"; } .glyphicon-phone-alt:before { content: "\e183"; } .glyphicon-tower:before { content: "\e184"; } .glyphicon-stats:before { content: "\e185"; } .glyphicon-sd-video:before { content: "\e186"; } .glyphicon-hd-video:before { content: "\e187"; } .glyphicon-subtitles:before { content: "\e188"; } .glyphicon-sound-stereo:before { content: "\e189"; } .glyphicon-sound-dolby:before { content: "\e190"; } .glyphicon-sound-5-1:before { content: "\e191"; } .glyphicon-sound-6-1:before { content: "\e192"; } .glyphicon-sound-7-1:before { content: "\e193"; } .glyphicon-copyright-mark:before { content: "\e194"; } .glyphicon-registration-mark:before { content: "\e195"; } .glyphicon-cloud-download:before { content: "\e197"; } .glyphicon-cloud-upload:before { content: "\e198"; } .glyphicon-tree-conifer:before { content: "\e199"; } .glyphicon-tree-deciduous:before { content: "\e200"; } .glyphicon-cd:before { content: "\e201"; } .glyphicon-save-file:before { content: "\e202"; } .glyphicon-open-file:before { content: "\e203"; } .glyphicon-level-up:before { content: "\e204"; } .glyphicon-copy:before { content: "\e205"; } .glyphicon-paste:before { content: "\e206"; } .glyphicon-alert:before { content: "\e209"; } .glyphicon-equalizer:before { content: "\e210"; } .glyphicon-king:before { content: "\e211"; } .glyphicon-queen:before { content: "\e212"; } .glyphicon-pawn:before { content: "\e213"; } .glyphicon-bishop:before { content: "\e214"; } .glyphicon-knight:before { content: "\e215"; } .glyphicon-baby-formula:before { content: "\e216"; } .glyphicon-tent:before { content: "\26fa"; } .glyphicon-blackboard:before { content: "\e218"; } .glyphicon-bed:before { content: "\e219"; } .glyphicon-apple:before { content: "\f8ff"; } .glyphicon-erase:before { content: "\e221"; } .glyphicon-hourglass:before { content: "\231b"; } .glyphicon-lamp:before { content: "\e223"; } .glyphicon-duplicate:before { content: "\e224"; } .glyphicon-piggy-bank:before { content: "\e225"; } .glyphicon-scissors:before { content: "\e226"; } .glyphicon-bitcoin:before { content: "\e227"; } .glyphicon-btc:before { content: "\e227"; } .glyphicon-xbt:before { content: "\e227"; } .glyphicon-yen:before { content: "\00a5"; } .glyphicon-jpy:before { content: "\00a5"; } .glyphicon-ruble:before { content: "\20bd"; } .glyphicon-rub:before { content: "\20bd"; } .glyphicon-scale:before { content: "\e230"; } .glyphicon-ice-lolly:before { content: "\e231"; } .glyphicon-ice-lolly-tasted:before { content: "\e232"; } .glyphicon-education:before { content: "\e233"; } .glyphicon-option-horizontal:before { content: "\e234"; } .glyphicon-option-vertical:before { content: "\e235"; } .glyphicon-menu-hamburger:before { content: "\e236"; } .glyphicon-modal-window:before { content: "\e237"; } .glyphicon-oil:before { content: "\e238"; } .glyphicon-grain:before { content: "\e239"; } .glyphicon-sunglasses:before { content: "\e240"; } .glyphicon-text-size:before { content: "\e241"; } .glyphicon-text-color:before { content: "\e242"; } .glyphicon-text-background:before { content: "\e243"; } .glyphicon-object-align-top:before { content: "\e244"; } .glyphicon-object-align-bottom:before { content: "\e245"; } .glyphicon-object-align-horizontal:before { content: "\e246"; } .glyphicon-object-align-left:before { content: "\e247"; } .glyphicon-object-align-vertical:before { content: "\e248"; } .glyphicon-object-align-right:before { content: "\e249"; } .glyphicon-triangle-right:before { content: "\e250"; } .glyphicon-triangle-left:before { content: "\e251"; } .glyphicon-triangle-bottom:before { content: "\e252"; } .glyphicon-triangle-top:before { content: "\e253"; } .glyphicon-console:before { content: "\e254"; } .glyphicon-superscript:before { content: "\e255"; } .glyphicon-subscript:before { content: "\e256"; } .glyphicon-menu-left:before { content: "\e257"; } .glyphicon-menu-right:before { content: "\e258"; } .glyphicon-menu-down:before { content: "\e259"; } .glyphicon-menu-up:before { content: "\e260"; } * { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } *:before, *:after { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } html { font-size: 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } body { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 14px; line-height: 1.42857143; color: #333333; background-color: #fff; } input, button, select, textarea { font-family: inherit; font-size: inherit; line-height: inherit; } a { color: #337ab7; text-decoration: none; } a:hover, a:focus { color: #23527c; text-decoration: underline; } a:focus { outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; } figure { margin: 0; } img { vertical-align: middle; } .img-responsive, .thumbnail > img, .thumbnail a > img, .carousel-inner > .item > img, .carousel-inner > .item > a > img { display: block; max-width: 100%; height: auto; } .img-rounded { border-radius: 6px; } .img-thumbnail { padding: 4px; line-height: 1.42857143; background-color: #fff; border: 1px solid #ddd; border-radius: 4px; -webkit-transition: all 0.2s ease-in-out; -o-transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out; display: inline-block; max-width: 100%; height: auto; } .img-circle { border-radius: 50%; } hr { margin-top: 20px; margin-bottom: 20px; border: 0; border-top: 1px solid #eeeeee; } .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); border: 0; } .sr-only-focusable:active, .sr-only-focusable:focus { position: static; width: auto; height: auto; margin: 0; overflow: visible; clip: auto; } [role="button"] { cursor: pointer; } h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 { font-family: inherit; font-weight: 500; line-height: 1.1; color: inherit; } h1 small, h2 small, h3 small, h4 small, h5 small, h6 small, .h1 small, .h2 small, .h3 small, .h4 small, .h5 small, .h6 small, h1 .small, h2 .small, h3 .small, h4 .small, h5 .small, h6 .small, .h1 .small, .h2 .small, .h3 .small, .h4 .small, .h5 .small, .h6 .small { font-weight: 400; line-height: 1; color: #777777; } h1, .h1, h2, .h2, h3, .h3 { margin-top: 20px; margin-bottom: 10px; } h1 small, .h1 small, h2 small, .h2 small, h3 small, .h3 small, h1 .small, .h1 .small, h2 .small, .h2 .small, h3 .small, .h3 .small { font-size: 65%; } h4, .h4, h5, .h5, h6, .h6 { margin-top: 10px; margin-bottom: 10px; } h4 small, .h4 small, h5 small, .h5 small, h6 small, .h6 small, h4 .small, .h4 .small, h5 .small, .h5 .small, h6 .small, .h6 .small { font-size: 75%; } h1, .h1 { font-size: 36px; } h2, .h2 { font-size: 30px; } h3, .h3 { font-size: 24px; } h4, .h4 { font-size: 18px; } h5, .h5 { font-size: 14px; } h6, .h6 { font-size: 12px; } p { margin: 0 0 10px; } .lead { margin-bottom: 20px; font-size: 16px; font-weight: 300; line-height: 1.4; } @media (min-width: 768px) { .lead { font-size: 21px; } } small, .small { font-size: 85%; } mark, .mark { padding: 0.2em; background-color: #fcf8e3; } .text-left { text-align: left; } .text-right { text-align: right; } .text-center { text-align: center; } .text-justify { text-align: justify; } .text-nowrap { white-space: nowrap; } .text-lowercase { text-transform: lowercase; } .text-uppercase { text-transform: uppercase; } .text-capitalize { text-transform: capitalize; } .text-muted { color: #777777; } .text-primary { color: #337ab7; } a.text-primary:hover, a.text-primary:focus { color: #286090; } .text-success { color: #3c763d; } a.text-success:hover, a.text-success:focus { color: #2b542c; } .text-info { color: #31708f; } a.text-info:hover, a.text-info:focus { color: #245269; } .text-warning { color: #8a6d3b; } a.text-warning:hover, a.text-warning:focus { color: #66512c; } .text-danger { color: #a94442; } a.text-danger:hover, a.text-danger:focus { color: #843534; } .bg-primary { color: #fff; background-color: #337ab7; } a.bg-primary:hover, a.bg-primary:focus { background-color: #286090; } .bg-success { background-color: #dff0d8; } a.bg-success:hover, a.bg-success:focus { background-color: #c1e2b3; } .bg-info { background-color: #d9edf7; } a.bg-info:hover, a.bg-info:focus { background-color: #afd9ee; } .bg-warning { background-color: #fcf8e3; } a.bg-warning:hover, a.bg-warning:focus { background-color: #f7ecb5; } .bg-danger { background-color: #f2dede; } a.bg-danger:hover, a.bg-danger:focus { background-color: #e4b9b9; } .page-header { padding-bottom: 9px; margin: 40px 0 20px; border-bottom: 1px solid #eeeeee; } ul, ol { margin-top: 0; margin-bottom: 10px; } ul ul, ol ul, ul ol, ol ol { margin-bottom: 0; } .list-unstyled { padding-left: 0; list-style: none; } .list-inline { padding-left: 0; list-style: none; margin-left: -5px; } .list-inline > li { display: inline-block; padding-right: 5px; padding-left: 5px; } dl { margin-top: 0; margin-bottom: 20px; } dt, dd { line-height: 1.42857143; } dt { font-weight: 700; } dd { margin-left: 0; } @media (min-width: 768px) { .dl-horizontal dt { float: left; width: 160px; clear: left; text-align: right; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .dl-horizontal dd { margin-left: 180px; } } abbr[title], abbr[data-original-title] { cursor: help; } .initialism { font-size: 90%; text-transform: uppercase; } blockquote { padding: 10px 20px; margin: 0 0 20px; font-size: 17.5px; border-left: 5px solid #eeeeee; } blockquote p:last-child, blockquote ul:last-child, blockquote ol:last-child { margin-bottom: 0; } blockquote footer, blockquote small, blockquote .small { display: block; font-size: 80%; line-height: 1.42857143; color: #777777; } blockquote footer:before, blockquote small:before, blockquote .small:before { content: "\2014 \00A0"; } .blockquote-reverse, blockquote.pull-right { padding-right: 15px; padding-left: 0; text-align: right; border-right: 5px solid #eeeeee; border-left: 0; } .blockquote-reverse footer:before, blockquote.pull-right footer:before, .blockquote-reverse small:before, blockquote.pull-right small:before, .blockquote-reverse .small:before, blockquote.pull-right .small:before { content: ""; } .blockquote-reverse footer:after, blockquote.pull-right footer:after, .blockquote-reverse small:after, blockquote.pull-right small:after, .blockquote-reverse .small:after, blockquote.pull-right .small:after { content: "\00A0 \2014"; } address { margin-bottom: 20px; font-style: normal; line-height: 1.42857143; } code, kbd, pre, samp { font-family: Menlo, Monaco, Consolas, "Courier New", monospace; } code { padding: 2px 4px; font-size: 90%; color: #c7254e; background-color: #f9f2f4; border-radius: 4px; } kbd { padding: 2px 4px; font-size: 90%; color: #fff; background-color: #333; border-radius: 3px; -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); } kbd kbd { padding: 0; font-size: 100%; font-weight: 700; -webkit-box-shadow: none; box-shadow: none; } pre { display: block; padding: 9.5px; margin: 0 0 10px; font-size: 13px; line-height: 1.42857143; color: #333333; word-break: break-all; word-wrap: break-word; background-color: #f5f5f5; border: 1px solid #ccc; border-radius: 4px; } pre code { padding: 0; font-size: inherit; color: inherit; white-space: pre-wrap; background-color: transparent; border-radius: 0; } .pre-scrollable { max-height: 340px; overflow-y: scroll; } .container { padding-right: 15px; padding-left: 15px; margin-right: auto; margin-left: auto; } @media (min-width: 768px) { .container { width: 750px; } } @media (min-width: 992px) { .container { width: 970px; } } @media (min-width: 1200px) { .container { width: 1170px; } } .container-fluid { padding-right: 15px; padding-left: 15px; margin-right: auto; margin-left: auto; } .row { margin-right: -15px; margin-left: -15px; } .row-no-gutters { margin-right: 0; margin-left: 0; } .row-no-gutters [class*="col-"] { padding-right: 0; padding-left: 0; } .col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { position: relative; min-height: 1px; padding-right: 15px; padding-left: 15px; } .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { float: left; } .col-xs-12 { width: 100%; } .col-xs-11 { width: 91.66666667%; } .col-xs-10 { width: 83.33333333%; } .col-xs-9 { width: 75%; } .col-xs-8 { width: 66.66666667%; } .col-xs-7 { width: 58.33333333%; } .col-xs-6 { width: 50%; } .col-xs-5 { width: 41.66666667%; } .col-xs-4 { width: 33.33333333%; } .col-xs-3 { width: 25%; } .col-xs-2 { width: 16.66666667%; } .col-xs-1 { width: 8.33333333%; } .col-xs-pull-12 { right: 100%; } .col-xs-pull-11 { right: 91.66666667%; } .col-xs-pull-10 { right: 83.33333333%; } .col-xs-pull-9 { right: 75%; } .col-xs-pull-8 { right: 66.66666667%; } .col-xs-pull-7 { right: 58.33333333%; } .col-xs-pull-6 { right: 50%; } .col-xs-pull-5 { right: 41.66666667%; } .col-xs-pull-4 { right: 33.33333333%; } .col-xs-pull-3 { right: 25%; } .col-xs-pull-2 { right: 16.66666667%; } .col-xs-pull-1 { right: 8.33333333%; } .col-xs-pull-0 { right: auto; } .col-xs-push-12 { left: 100%; } .col-xs-push-11 { left: 91.66666667%; } .col-xs-push-10 { left: 83.33333333%; } .col-xs-push-9 { left: 75%; } .col-xs-push-8 { left: 66.66666667%; } .col-xs-push-7 { left: 58.33333333%; } .col-xs-push-6 { left: 50%; } .col-xs-push-5 { left: 41.66666667%; } .col-xs-push-4 { left: 33.33333333%; } .col-xs-push-3 { left: 25%; } .col-xs-push-2 { left: 16.66666667%; } .col-xs-push-1 { left: 8.33333333%; } .col-xs-push-0 { left: auto; } .col-xs-offset-12 { margin-left: 100%; } .col-xs-offset-11 { margin-left: 91.66666667%; } .col-xs-offset-10 { margin-left: 83.33333333%; } .col-xs-offset-9 { margin-left: 75%; } .col-xs-offset-8 { margin-left: 66.66666667%; } .col-xs-offset-7 { margin-left: 58.33333333%; } .col-xs-offset-6 { margin-left: 50%; } .col-xs-offset-5 { margin-left: 41.66666667%; } .col-xs-offset-4 { margin-left: 33.33333333%; } .col-xs-offset-3 { margin-left: 25%; } .col-xs-offset-2 { margin-left: 16.66666667%; } .col-xs-offset-1 { margin-left: 8.33333333%; } .col-xs-offset-0 { margin-left: 0%; } @media (min-width: 768px) { .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { float: left; } .col-sm-12 { width: 100%; } .col-sm-11 { width: 91.66666667%; } .col-sm-10 { width: 83.33333333%; } .col-sm-9 { width: 75%; } .col-sm-8 { width: 66.66666667%; } .col-sm-7 { width: 58.33333333%; } .col-sm-6 { width: 50%; } .col-sm-5 { width: 41.66666667%; } .col-sm-4 { width: 33.33333333%; } .col-sm-3 { width: 25%; } .col-sm-2 { width: 16.66666667%; } .col-sm-1 { width: 8.33333333%; } .col-sm-pull-12 { right: 100%; } .col-sm-pull-11 { right: 91.66666667%; } .col-sm-pull-10 { right: 83.33333333%; } .col-sm-pull-9 { right: 75%; } .col-sm-pull-8 { right: 66.66666667%; } .col-sm-pull-7 { right: 58.33333333%; } .col-sm-pull-6 { right: 50%; } .col-sm-pull-5 { right: 41.66666667%; } .col-sm-pull-4 { right: 33.33333333%; } .col-sm-pull-3 { right: 25%; } .col-sm-pull-2 { right: 16.66666667%; } .col-sm-pull-1 { right: 8.33333333%; } .col-sm-pull-0 { right: auto; } .col-sm-push-12 { left: 100%; } .col-sm-push-11 { left: 91.66666667%; } .col-sm-push-10 { left: 83.33333333%; } .col-sm-push-9 { left: 75%; } .col-sm-push-8 { left: 66.66666667%; } .col-sm-push-7 { left: 58.33333333%; } .col-sm-push-6 { left: 50%; } .col-sm-push-5 { left: 41.66666667%; } .col-sm-push-4 { left: 33.33333333%; } .col-sm-push-3 { left: 25%; } .col-sm-push-2 { left: 16.66666667%; } .col-sm-push-1 { left: 8.33333333%; } .col-sm-push-0 { left: auto; } .col-sm-offset-12 { margin-left: 100%; } .col-sm-offset-11 { margin-left: 91.66666667%; } .col-sm-offset-10 { margin-left: 83.33333333%; } .col-sm-offset-9 { margin-left: 75%; } .col-sm-offset-8 { margin-left: 66.66666667%; } .col-sm-offset-7 { margin-left: 58.33333333%; } .col-sm-offset-6 { margin-left: 50%; } .col-sm-offset-5 { margin-left: 41.66666667%; } .col-sm-offset-4 { margin-left: 33.33333333%; } .col-sm-offset-3 { margin-left: 25%; } .col-sm-offset-2 { margin-left: 16.66666667%; } .col-sm-offset-1 { margin-left: 8.33333333%; } .col-sm-offset-0 { margin-left: 0%; } } @media (min-width: 992px) { .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { float: left; } .col-md-12 { width: 100%; } .col-md-11 { width: 91.66666667%; } .col-md-10 { width: 83.33333333%; } .col-md-9 { width: 75%; } .col-md-8 { width: 66.66666667%; } .col-md-7 { width: 58.33333333%; } .col-md-6 { width: 50%; } .col-md-5 { width: 41.66666667%; } .col-md-4 { width: 33.33333333%; } .col-md-3 { width: 25%; } .col-md-2 { width: 16.66666667%; } .col-md-1 { width: 8.33333333%; } .col-md-pull-12 { right: 100%; } .col-md-pull-11 { right: 91.66666667%; } .col-md-pull-10 { right: 83.33333333%; } .col-md-pull-9 { right: 75%; } .col-md-pull-8 { right: 66.66666667%; } .col-md-pull-7 { right: 58.33333333%; } .col-md-pull-6 { right: 50%; } .col-md-pull-5 { right: 41.66666667%; } .col-md-pull-4 { right: 33.33333333%; } .col-md-pull-3 { right: 25%; } .col-md-pull-2 { right: 16.66666667%; } .col-md-pull-1 { right: 8.33333333%; } .col-md-pull-0 { right: auto; } .col-md-push-12 { left: 100%; } .col-md-push-11 { left: 91.66666667%; } .col-md-push-10 { left: 83.33333333%; } .col-md-push-9 { left: 75%; } .col-md-push-8 { left: 66.66666667%; } .col-md-push-7 { left: 58.33333333%; } .col-md-push-6 { left: 50%; } .col-md-push-5 { left: 41.66666667%; } .col-md-push-4 { left: 33.33333333%; } .col-md-push-3 { left: 25%; } .col-md-push-2 { left: 16.66666667%; } .col-md-push-1 { left: 8.33333333%; } .col-md-push-0 { left: auto; } .col-md-offset-12 { margin-left: 100%; } .col-md-offset-11 { margin-left: 91.66666667%; } .col-md-offset-10 { margin-left: 83.33333333%; } .col-md-offset-9 { margin-left: 75%; } .col-md-offset-8 { margin-left: 66.66666667%; } .col-md-offset-7 { margin-left: 58.33333333%; } .col-md-offset-6 { margin-left: 50%; } .col-md-offset-5 { margin-left: 41.66666667%; } .col-md-offset-4 { margin-left: 33.33333333%; } .col-md-offset-3 { margin-left: 25%; } .col-md-offset-2 { margin-left: 16.66666667%; } .col-md-offset-1 { margin-left: 8.33333333%; } .col-md-offset-0 { margin-left: 0%; } } @media (min-width: 1200px) { .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { float: left; } .col-lg-12 { width: 100%; } .col-lg-11 { width: 91.66666667%; } .col-lg-10 { width: 83.33333333%; } .col-lg-9 { width: 75%; } .col-lg-8 { width: 66.66666667%; } .col-lg-7 { width: 58.33333333%; } .col-lg-6 { width: 50%; } .col-lg-5 { width: 41.66666667%; } .col-lg-4 { width: 33.33333333%; } .col-lg-3 { width: 25%; } .col-lg-2 { width: 16.66666667%; } .col-lg-1 { width: 8.33333333%; } .col-lg-pull-12 { right: 100%; } .col-lg-pull-11 { right: 91.66666667%; } .col-lg-pull-10 { right: 83.33333333%; } .col-lg-pull-9 { right: 75%; } .col-lg-pull-8 { right: 66.66666667%; } .col-lg-pull-7 { right: 58.33333333%; } .col-lg-pull-6 { right: 50%; } .col-lg-pull-5 { right: 41.66666667%; } .col-lg-pull-4 { right: 33.33333333%; } .col-lg-pull-3 { right: 25%; } .col-lg-pull-2 { right: 16.66666667%; } .col-lg-pull-1 { right: 8.33333333%; } .col-lg-pull-0 { right: auto; } .col-lg-push-12 { left: 100%; } .col-lg-push-11 { left: 91.66666667%; } .col-lg-push-10 { left: 83.33333333%; } .col-lg-push-9 { left: 75%; } .col-lg-push-8 { left: 66.66666667%; } .col-lg-push-7 { left: 58.33333333%; } .col-lg-push-6 { left: 50%; } .col-lg-push-5 { left: 41.66666667%; } .col-lg-push-4 { left: 33.33333333%; } .col-lg-push-3 { left: 25%; } .col-lg-push-2 { left: 16.66666667%; } .col-lg-push-1 { left: 8.33333333%; } .col-lg-push-0 { left: auto; } .col-lg-offset-12 { margin-left: 100%; } .col-lg-offset-11 { margin-left: 91.66666667%; } .col-lg-offset-10 { margin-left: 83.33333333%; } .col-lg-offset-9 { margin-left: 75%; } .col-lg-offset-8 { margin-left: 66.66666667%; } .col-lg-offset-7 { margin-left: 58.33333333%; } .col-lg-offset-6 { margin-left: 50%; } .col-lg-offset-5 { margin-left: 41.66666667%; } .col-lg-offset-4 { margin-left: 33.33333333%; } .col-lg-offset-3 { margin-left: 25%; } .col-lg-offset-2 { margin-left: 16.66666667%; } .col-lg-offset-1 { margin-left: 8.33333333%; } .col-lg-offset-0 { margin-left: 0%; } } table { background-color: transparent; } table col[class*="col-"] { position: static; display: table-column; float: none; } table td[class*="col-"], table th[class*="col-"] { position: static; display: table-cell; float: none; } caption { padding-top: 8px; padding-bottom: 8px; color: #777777; text-align: left; } th { text-align: left; } .table { width: 100%; max-width: 100%; margin-bottom: 20px; } .table > thead > tr > th, .table > tbody > tr > th, .table > tfoot > tr > th, .table > thead > tr > td, .table > tbody > tr > td, .table > tfoot > tr > td { padding: 8px; line-height: 1.42857143; vertical-align: top; border-top: 1px solid #ddd; } .table > thead > tr > th { vertical-align: bottom; border-bottom: 2px solid #ddd; } .table > caption + thead > tr:first-child > th, .table > colgroup + thead > tr:first-child > th, .table > thead:first-child > tr:first-child > th, .table > caption + thead > tr:first-child > td, .table > colgroup + thead > tr:first-child > td, .table > thead:first-child > tr:first-child > td { border-top: 0; } .table > tbody + tbody { border-top: 2px solid #ddd; } .table .table { background-color: #fff; } .table-condensed > thead > tr > th, .table-condensed > tbody > tr > th, .table-condensed > tfoot > tr > th, .table-condensed > thead > tr > td, .table-condensed > tbody > tr > td, .table-condensed > tfoot > tr > td { padding: 5px; } .table-bordered { border: 1px solid #ddd; } .table-bordered > thead > tr > th, .table-bordered > tbody > tr > th, .table-bordered > tfoot > tr > th, .table-bordered > thead > tr > td, .table-bordered > tbody > tr > td, .table-bordered > tfoot > tr > td { border: 1px solid #ddd; } .table-bordered > thead > tr > th, .table-bordered > thead > tr > td { border-bottom-width: 2px; } .table-striped > tbody > tr:nth-of-type(odd) { background-color: #f9f9f9; } .table-hover > tbody > tr:hover { background-color: #f5f5f5; } .table > thead > tr > td.active, .table > tbody > tr > td.active, .table > tfoot > tr > td.active, .table > thead > tr > th.active, .table > tbody > tr > th.active, .table > tfoot > tr > th.active, .table > thead > tr.active > td, .table > tbody > tr.active > td, .table > tfoot > tr.active > td, .table > thead > tr.active > th, .table > tbody > tr.active > th, .table > tfoot > tr.active > th { background-color: #f5f5f5; } .table-hover > tbody > tr > td.active:hover, .table-hover > tbody > tr > th.active:hover, .table-hover > tbody > tr.active:hover > td, .table-hover > tbody > tr:hover > .active, .table-hover > tbody > tr.active:hover > th { background-color: #e8e8e8; } .table > thead > tr > td.success, .table > tbody > tr > td.success, .table > tfoot > tr > td.success, .table > thead > tr > th.success, .table > tbody > tr > th.success, .table > tfoot > tr > th.success, .table > thead > tr.success > td, .table > tbody > tr.success > td, .table > tfoot > tr.success > td, .table > thead > tr.success > th, .table > tbody > tr.success > th, .table > tfoot > tr.success > th { background-color: #dff0d8; } .table-hover > tbody > tr > td.success:hover, .table-hover > tbody > tr > th.success:hover, .table-hover > tbody > tr.success:hover > td, .table-hover > tbody > tr:hover > .success, .table-hover > tbody > tr.success:hover > th { background-color: #d0e9c6; } .table > thead > tr > td.info, .table > tbody > tr > td.info, .table > tfoot > tr > td.info, .table > thead > tr > th.info, .table > tbody > tr > th.info, .table > tfoot > tr > th.info, .table > thead > tr.info > td, .table > tbody > tr.info > td, .table > tfoot > tr.info > td, .table > thead > tr.info > th, .table > tbody > tr.info > th, .table > tfoot > tr.info > th { background-color: #d9edf7; } .table-hover > tbody > tr > td.info:hover, .table-hover > tbody > tr > th.info:hover, .table-hover > tbody > tr.info:hover > td, .table-hover > tbody > tr:hover > .info, .table-hover > tbody > tr.info:hover > th { background-color: #c4e3f3; } .table > thead > tr > td.warning, .table > tbody > tr > td.warning, .table > tfoot > tr > td.warning, .table > thead > tr > th.warning, .table > tbody > tr > th.warning, .table > tfoot > tr > th.warning, .table > thead > tr.warning > td, .table > tbody > tr.warning > td, .table > tfoot > tr.warning > td, .table > thead > tr.warning > th, .table > tbody > tr.warning > th, .table > tfoot > tr.warning > th { background-color: #fcf8e3; } .table-hover > tbody > tr > td.warning:hover, .table-hover > tbody > tr > th.warning:hover, .table-hover > tbody > tr.warning:hover > td, .table-hover > tbody > tr:hover > .warning, .table-hover > tbody > tr.warning:hover > th { background-color: #faf2cc; } .table > thead > tr > td.danger, .table > tbody > tr > td.danger, .table > tfoot > tr > td.danger, .table > thead > tr > th.danger, .table > tbody > tr > th.danger, .table > tfoot > tr > th.danger, .table > thead > tr.danger > td, .table > tbody > tr.danger > td, .table > tfoot > tr.danger > td, .table > thead > tr.danger > th, .table > tbody > tr.danger > th, .table > tfoot > tr.danger > th { background-color: #f2dede; } .table-hover > tbody > tr > td.danger:hover, .table-hover > tbody > tr > th.danger:hover, .table-hover > tbody > tr.danger:hover > td, .table-hover > tbody > tr:hover > .danger, .table-hover > tbody > tr.danger:hover > th { background-color: #ebcccc; } .table-responsive { min-height: 0.01%; overflow-x: auto; } @media screen and (max-width: 767px) { .table-responsive { width: 100%; margin-bottom: 15px; overflow-y: hidden; -ms-overflow-style: -ms-autohiding-scrollbar; border: 1px solid #ddd; } .table-responsive > .table { margin-bottom: 0; } .table-responsive > .table > thead > tr > th, .table-responsive > .table > tbody > tr > th, .table-responsive > .table > tfoot > tr > th, .table-responsive > .table > thead > tr > td, .table-responsive > .table > tbody > tr > td, .table-responsive > .table > tfoot > tr > td { white-space: nowrap; } .table-responsive > .table-bordered { border: 0; } .table-responsive > .table-bordered > thead > tr > th:first-child, .table-responsive > .table-bordered > tbody > tr > th:first-child, .table-responsive > .table-bordered > tfoot > tr > th:first-child, .table-responsive > .table-bordered > thead > tr > td:first-child, .table-responsive > .table-bordered > tbody > tr > td:first-child, .table-responsive > .table-bordered > tfoot > tr > td:first-child { border-left: 0; } .table-responsive > .table-bordered > thead > tr > th:last-child, .table-responsive > .table-bordered > tbody > tr > th:last-child, .table-responsive > .table-bordered > tfoot > tr > th:last-child, .table-responsive > .table-bordered > thead > tr > td:last-child, .table-responsive > .table-bordered > tbody > tr > td:last-child, .table-responsive > .table-bordered > tfoot > tr > td:last-child { border-right: 0; } .table-responsive > .table-bordered > tbody > tr:last-child > th, .table-responsive > .table-bordered > tfoot > tr:last-child > th, .table-responsive > .table-bordered > tbody > tr:last-child > td, .table-responsive > .table-bordered > tfoot > tr:last-child > td { border-bottom: 0; } } fieldset { min-width: 0; padding: 0; margin: 0; border: 0; } legend { display: block; width: 100%; padding: 0; margin-bottom: 20px; font-size: 21px; line-height: inherit; color: #333333; border: 0; border-bottom: 1px solid #e5e5e5; } label { display: inline-block; max-width: 100%; margin-bottom: 5px; font-weight: 700; } input[type="search"] { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; -webkit-appearance: none; -moz-appearance: none; appearance: none; } input[type="radio"], input[type="checkbox"] { margin: 4px 0 0; margin-top: 1px \9; line-height: normal; } input[type="radio"][disabled], input[type="checkbox"][disabled], input[type="radio"].disabled, input[type="checkbox"].disabled, fieldset[disabled] input[type="radio"], fieldset[disabled] input[type="checkbox"] { cursor: not-allowed; } input[type="file"] { display: block; } input[type="range"] { display: block; width: 100%; } select[multiple], select[size] { height: auto; } input[type="file"]:focus, input[type="radio"]:focus, input[type="checkbox"]:focus { outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; } output { display: block; padding-top: 7px; font-size: 14px; line-height: 1.42857143; color: #555555; } .form-control { display: block; width: 100%; height: 34px; padding: 6px 12px; font-size: 14px; line-height: 1.42857143; color: #555555; background-color: #fff; background-image: none; border: 1px solid #ccc; border-radius: 4px; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; } .form-control:focus { border-color: #66afe9; outline: 0; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, 0.6); box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, 0.6); } .form-control::-moz-placeholder { color: #999; opacity: 1; } .form-control:-ms-input-placeholder { color: #999; } .form-control::-webkit-input-placeholder { color: #999; } .form-control::-ms-expand { background-color: transparent; border: 0; } .form-control[disabled], .form-control[readonly], fieldset[disabled] .form-control { background-color: #eeeeee; opacity: 1; } .form-control[disabled], fieldset[disabled] .form-control { cursor: not-allowed; } textarea.form-control { height: auto; } @media screen and (-webkit-min-device-pixel-ratio: 0) { input[type="date"].form-control, input[type="time"].form-control, input[type="datetime-local"].form-control, input[type="month"].form-control { line-height: 34px; } input[type="date"].input-sm, input[type="time"].input-sm, input[type="datetime-local"].input-sm, input[type="month"].input-sm, .input-group-sm input[type="date"], .input-group-sm input[type="time"], .input-group-sm input[type="datetime-local"], .input-group-sm input[type="month"] { line-height: 30px; } input[type="date"].input-lg, input[type="time"].input-lg, input[type="datetime-local"].input-lg, input[type="month"].input-lg, .input-group-lg input[type="date"], .input-group-lg input[type="time"], .input-group-lg input[type="datetime-local"], .input-group-lg input[type="month"] { line-height: 46px; } } .form-group { margin-bottom: 15px; } .radio, .checkbox { position: relative; display: block; margin-top: 10px; margin-bottom: 10px; } .radio.disabled label, .checkbox.disabled label, fieldset[disabled] .radio label, fieldset[disabled] .checkbox label { cursor: not-allowed; } .radio label, .checkbox label { min-height: 20px; padding-left: 20px; margin-bottom: 0; font-weight: 400; cursor: pointer; } .radio input[type="radio"], .radio-inline input[type="radio"], .checkbox input[type="checkbox"], .checkbox-inline input[type="checkbox"] { position: absolute; margin-top: 4px \9; margin-left: -20px; } .radio + .radio, .checkbox + .checkbox { margin-top: -5px; } .radio-inline, .checkbox-inline { position: relative; display: inline-block; padding-left: 20px; margin-bottom: 0; font-weight: 400; vertical-align: middle; cursor: pointer; } .radio-inline.disabled, .checkbox-inline.disabled, fieldset[disabled] .radio-inline, fieldset[disabled] .checkbox-inline { cursor: not-allowed; } .radio-inline + .radio-inline, .checkbox-inline + .checkbox-inline { margin-top: 0; margin-left: 10px; } .form-control-static { min-height: 34px; padding-top: 7px; padding-bottom: 7px; margin-bottom: 0; } .form-control-static.input-lg, .form-control-static.input-sm { padding-right: 0; padding-left: 0; } .input-sm { height: 30px; padding: 5px 10px; font-size: 12px; line-height: 1.5; border-radius: 3px; } select.input-sm { height: 30px; line-height: 30px; } textarea.input-sm, select[multiple].input-sm { height: auto; } .form-group-sm .form-control { height: 30px; padding: 5px 10px; font-size: 12px; line-height: 1.5; border-radius: 3px; } .form-group-sm select.form-control { height: 30px; line-height: 30px; } .form-group-sm textarea.form-control, .form-group-sm select[multiple].form-control { height: auto; } .form-group-sm .form-control-static { height: 30px; min-height: 32px; padding: 6px 10px; font-size: 12px; line-height: 1.5; } .input-lg { height: 46px; padding: 10px 16px; font-size: 18px; line-height: 1.3333333; border-radius: 6px; } select.input-lg { height: 46px; line-height: 46px; } textarea.input-lg, select[multiple].input-lg { height: auto; } .form-group-lg .form-control { height: 46px; padding: 10px 16px; font-size: 18px; line-height: 1.3333333; border-radius: 6px; } .form-group-lg select.form-control { height: 46px; line-height: 46px; } .form-group-lg textarea.form-control, .form-group-lg select[multiple].form-control { height: auto; } .form-group-lg .form-control-static { height: 46px; min-height: 38px; padding: 11px 16px; font-size: 18px; line-height: 1.3333333; } .has-feedback { position: relative; } .has-feedback .form-control { padding-right: 42.5px; } .form-control-feedback { position: absolute; top: 0; right: 0; z-index: 2; display: block; width: 34px; height: 34px; line-height: 34px; text-align: center; pointer-events: none; } .input-lg + .form-control-feedback, .input-group-lg + .form-control-feedback, .form-group-lg .form-control + .form-control-feedback { width: 46px; height: 46px; line-height: 46px; } .input-sm + .form-control-feedback, .input-group-sm + .form-control-feedback, .form-group-sm .form-control + .form-control-feedback { width: 30px; height: 30px; line-height: 30px; } .has-success .help-block, .has-success .control-label, .has-success .radio, .has-success .checkbox, .has-success .radio-inline, .has-success .checkbox-inline, .has-success.radio label, .has-success.checkbox label, .has-success.radio-inline label, .has-success.checkbox-inline label { color: #3c763d; } .has-success .form-control { border-color: #3c763d; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); } .has-success .form-control:focus { border-color: #2b542c; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; } .has-success .input-group-addon { color: #3c763d; background-color: #dff0d8; border-color: #3c763d; } .has-success .form-control-feedback { color: #3c763d; } .has-warning .help-block, .has-warning .control-label, .has-warning .radio, .has-warning .checkbox, .has-warning .radio-inline, .has-warning .checkbox-inline, .has-warning.radio label, .has-warning.checkbox label, .has-warning.radio-inline label, .has-warning.checkbox-inline label { color: #8a6d3b; } .has-warning .form-control { border-color: #8a6d3b; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); } .has-warning .form-control:focus { border-color: #66512c; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; } .has-warning .input-group-addon { color: #8a6d3b; background-color: #fcf8e3; border-color: #8a6d3b; } .has-warning .form-control-feedback { color: #8a6d3b; } .has-error .help-block, .has-error .control-label, .has-error .radio, .has-error .checkbox, .has-error .radio-inline, .has-error .checkbox-inline, .has-error.radio label, .has-error.checkbox label, .has-error.radio-inline label, .has-error.checkbox-inline label { color: #a94442; } .has-error .form-control { border-color: #a94442; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); } .has-error .form-control:focus { border-color: #843534; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; } .has-error .input-group-addon { color: #a94442; background-color: #f2dede; border-color: #a94442; } .has-error .form-control-feedback { color: #a94442; } .has-feedback label ~ .form-control-feedback { top: 25px; } .has-feedback label.sr-only ~ .form-control-feedback { top: 0; } .help-block { display: block; margin-top: 5px; margin-bottom: 10px; color: #737373; } @media (min-width: 768px) { .form-inline .form-group { display: inline-block; margin-bottom: 0; vertical-align: middle; } .form-inline .form-control { display: inline-block; width: auto; vertical-align: middle; } .form-inline .form-control-static { display: inline-block; } .form-inline .input-group { display: inline-table; vertical-align: middle; } .form-inline .input-group .input-group-addon, .form-inline .input-group .input-group-btn, .form-inline .input-group .form-control { width: auto; } .form-inline .input-group > .form-control { width: 100%; } .form-inline .control-label { margin-bottom: 0; vertical-align: middle; } .form-inline .radio, .form-inline .checkbox { display: inline-block; margin-top: 0; margin-bottom: 0; vertical-align: middle; } .form-inline .radio label, .form-inline .checkbox label { padding-left: 0; } .form-inline .radio input[type="radio"], .form-inline .checkbox input[type="checkbox"] { position: relative; margin-left: 0; } .form-inline .has-feedback .form-control-feedback { top: 0; } } .form-horizontal .radio, .form-horizontal .checkbox, .form-horizontal .radio-inline, .form-horizontal .checkbox-inline { padding-top: 7px; margin-top: 0; margin-bottom: 0; } .form-horizontal .radio, .form-horizontal .checkbox { min-height: 27px; } .form-horizontal .form-group { margin-right: -15px; margin-left: -15px; } @media (min-width: 768px) { .form-horizontal .control-label { padding-top: 7px; margin-bottom: 0; text-align: right; } } .form-horizontal .has-feedback .form-control-feedback { right: 15px; } @media (min-width: 768px) { .form-horizontal .form-group-lg .control-label { padding-top: 11px; font-size: 18px; } } @media (min-width: 768px) { .form-horizontal .form-group-sm .control-label { padding-top: 6px; font-size: 12px; } } .btn { display: inline-block; margin-bottom: 0; font-weight: normal; text-align: center; white-space: nowrap; vertical-align: middle; -ms-touch-action: manipulation; touch-action: manipulation; cursor: pointer; background-image: none; border: 1px solid transparent; padding: 6px 12px; font-size: 14px; line-height: 1.42857143; border-radius: 4px; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .btn:focus, .btn:active:focus, .btn.active:focus, .btn.focus, .btn:active.focus, .btn.active.focus { outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; } .btn:hover, .btn:focus, .btn.focus { color: #333; text-decoration: none; } .btn:active, .btn.active { background-image: none; outline: 0; -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); } .btn.disabled, .btn[disabled], fieldset[disabled] .btn { cursor: not-allowed; filter: alpha(opacity=65); opacity: 0.65; -webkit-box-shadow: none; box-shadow: none; } a.btn.disabled, fieldset[disabled] a.btn { pointer-events: none; } .btn-default { color: #333; background-color: #fff; border-color: #ccc; } .btn-default:focus, .btn-default.focus { color: #333; background-color: #e6e6e6; border-color: #8c8c8c; } .btn-default:hover { color: #333; background-color: #e6e6e6; border-color: #adadad; } .btn-default:active, .btn-default.active, .open > .dropdown-toggle.btn-default { color: #333; background-color: #e6e6e6; background-image: none; border-color: #adadad; } .btn-default:active:hover, .btn-default.active:hover, .open > .dropdown-toggle.btn-default:hover, .btn-default:active:focus, .btn-default.active:focus, .open > .dropdown-toggle.btn-default:focus, .btn-default:active.focus, .btn-default.active.focus, .open > .dropdown-toggle.btn-default.focus { color: #333; background-color: #d4d4d4; border-color: #8c8c8c; } .btn-default.disabled:hover, .btn-default[disabled]:hover, fieldset[disabled] .btn-default:hover, .btn-default.disabled:focus, .btn-default[disabled]:focus, fieldset[disabled] .btn-default:focus, .btn-default.disabled.focus, .btn-default[disabled].focus, fieldset[disabled] .btn-default.focus { background-color: #fff; border-color: #ccc; } .btn-default .badge { color: #fff; background-color: #333; } .btn-primary { color: #fff; background-color: #337ab7; border-color: #2e6da4; } .btn-primary:focus, .btn-primary.focus { color: #fff; background-color: #286090; border-color: #122b40; } .btn-primary:hover { color: #fff; background-color: #286090; border-color: #204d74; } .btn-primary:active, .btn-primary.active, .open > .dropdown-toggle.btn-primary { color: #fff; background-color: #286090; background-image: none; border-color: #204d74; } .btn-primary:active:hover, .btn-primary.active:hover, .open > .dropdown-toggle.btn-primary:hover, .btn-primary:active:focus, .btn-primary.active:focus, .open > .dropdown-toggle.btn-primary:focus, .btn-primary:active.focus, .btn-primary.active.focus, .open > .dropdown-toggle.btn-primary.focus { color: #fff; background-color: #204d74; border-color: #122b40; } .btn-primary.disabled:hover, .btn-primary[disabled]:hover, fieldset[disabled] .btn-primary:hover, .btn-primary.disabled:focus, .btn-primary[disabled]:focus, fieldset[disabled] .btn-primary:focus, .btn-primary.disabled.focus, .btn-primary[disabled].focus, fieldset[disabled] .btn-primary.focus { background-color: #337ab7; border-color: #2e6da4; } .btn-primary .badge { color: #337ab7; background-color: #fff; } .btn-success { color: #fff; background-color: #5cb85c; border-color: #4cae4c; } .btn-success:focus, .btn-success.focus { color: #fff; background-color: #449d44; border-color: #255625; } .btn-success:hover { color: #fff; background-color: #449d44; border-color: #398439; } .btn-success:active, .btn-success.active, .open > .dropdown-toggle.btn-success { color: #fff; background-color: #449d44; background-image: none; border-color: #398439; } .btn-success:active:hover, .btn-success.active:hover, .open > .dropdown-toggle.btn-success:hover, .btn-success:active:focus, .btn-success.active:focus, .open > .dropdown-toggle.btn-success:focus, .btn-success:active.focus, .btn-success.active.focus, .open > .dropdown-toggle.btn-success.focus { color: #fff; background-color: #398439; border-color: #255625; } .btn-success.disabled:hover, .btn-success[disabled]:hover, fieldset[disabled] .btn-success:hover, .btn-success.disabled:focus, .btn-success[disabled]:focus, fieldset[disabled] .btn-success:focus, .btn-success.disabled.focus, .btn-success[disabled].focus, fieldset[disabled] .btn-success.focus { background-color: #5cb85c; border-color: #4cae4c; } .btn-success .badge { color: #5cb85c; background-color: #fff; } .btn-info { color: #fff; background-color: #5bc0de; border-color: #46b8da; } .btn-info:focus, .btn-info.focus { color: #fff; background-color: #31b0d5; border-color: #1b6d85; } .btn-info:hover { color: #fff; background-color: #31b0d5; border-color: #269abc; } .btn-info:active, .btn-info.active, .open > .dropdown-toggle.btn-info { color: #fff; background-color: #31b0d5; background-image: none; border-color: #269abc; } .btn-info:active:hover, .btn-info.active:hover, .open > .dropdown-toggle.btn-info:hover, .btn-info:active:focus, .btn-info.active:focus, .open > .dropdown-toggle.btn-info:focus, .btn-info:active.focus, .btn-info.active.focus, .open > .dropdown-toggle.btn-info.focus { color: #fff; background-color: #269abc; border-color: #1b6d85; } .btn-info.disabled:hover, .btn-info[disabled]:hover, fieldset[disabled] .btn-info:hover, .btn-info.disabled:focus, .btn-info[disabled]:focus, fieldset[disabled] .btn-info:focus, .btn-info.disabled.focus, .btn-info[disabled].focus, fieldset[disabled] .btn-info.focus { background-color: #5bc0de; border-color: #46b8da; } .btn-info .badge { color: #5bc0de; background-color: #fff; } .btn-warning { color: #fff; background-color: #f0ad4e; border-color: #eea236; } .btn-warning:focus, .btn-warning.focus { color: #fff; background-color: #ec971f; border-color: #985f0d; } .btn-warning:hover { color: #fff; background-color: #ec971f; border-color: #d58512; } .btn-warning:active, .btn-warning.active, .open > .dropdown-toggle.btn-warning { color: #fff; background-color: #ec971f; background-image: none; border-color: #d58512; } .btn-warning:active:hover, .btn-warning.active:hover, .open > .dropdown-toggle.btn-warning:hover, .btn-warning:active:focus, .btn-warning.active:focus, .open > .dropdown-toggle.btn-warning:focus, .btn-warning:active.focus, .btn-warning.active.focus, .open > .dropdown-toggle.btn-warning.focus { color: #fff; background-color: #d58512; border-color: #985f0d; } .btn-warning.disabled:hover, .btn-warning[disabled]:hover, fieldset[disabled] .btn-warning:hover, .btn-warning.disabled:focus, .btn-warning[disabled]:focus, fieldset[disabled] .btn-warning:focus, .btn-warning.disabled.focus, .btn-warning[disabled].focus, fieldset[disabled] .btn-warning.focus { background-color: #f0ad4e; border-color: #eea236; } .btn-warning .badge { color: #f0ad4e; background-color: #fff; } .btn-danger { color: #fff; background-color: #d9534f; border-color: #d43f3a; } .btn-danger:focus, .btn-danger.focus { color: #fff; background-color: #c9302c; border-color: #761c19; } .btn-danger:hover { color: #fff; background-color: #c9302c; border-color: #ac2925; } .btn-danger:active, .btn-danger.active, .open > .dropdown-toggle.btn-danger { color: #fff; background-color: #c9302c; background-image: none; border-color: #ac2925; } .btn-danger:active:hover, .btn-danger.active:hover, .open > .dropdown-toggle.btn-danger:hover, .btn-danger:active:focus, .btn-danger.active:focus, .open > .dropdown-toggle.btn-danger:focus, .btn-danger:active.focus, .btn-danger.active.focus, .open > .dropdown-toggle.btn-danger.focus { color: #fff; background-color: #ac2925; border-color: #761c19; } .btn-danger.disabled:hover, .btn-danger[disabled]:hover, fieldset[disabled] .btn-danger:hover, .btn-danger.disabled:focus, .btn-danger[disabled]:focus, fieldset[disabled] .btn-danger:focus, .btn-danger.disabled.focus, .btn-danger[disabled].focus, fieldset[disabled] .btn-danger.focus { background-color: #d9534f; border-color: #d43f3a; } .btn-danger .badge { color: #d9534f; background-color: #fff; } .btn-link { font-weight: 400; color: #337ab7; border-radius: 0; } .btn-link, .btn-link:active, .btn-link.active, .btn-link[disabled], fieldset[disabled] .btn-link { background-color: transparent; -webkit-box-shadow: none; box-shadow: none; } .btn-link, .btn-link:hover, .btn-link:focus, .btn-link:active { border-color: transparent; } .btn-link:hover, .btn-link:focus { color: #23527c; text-decoration: underline; background-color: transparent; } .btn-link[disabled]:hover, fieldset[disabled] .btn-link:hover, .btn-link[disabled]:focus, fieldset[disabled] .btn-link:focus { color: #777777; text-decoration: none; } .btn-lg, .btn-group-lg > .btn { padding: 10px 16px; font-size: 18px; line-height: 1.3333333; border-radius: 6px; } .btn-sm, .btn-group-sm > .btn { padding: 5px 10px; font-size: 12px; line-height: 1.5; border-radius: 3px; } .btn-xs, .btn-group-xs > .btn { padding: 1px 5px; font-size: 12px; line-height: 1.5; border-radius: 3px; } .btn-block { display: block; width: 100%; } .btn-block + .btn-block { margin-top: 5px; } input[type="submit"].btn-block, input[type="reset"].btn-block, input[type="button"].btn-block { width: 100%; } .fade { opacity: 0; -webkit-transition: opacity 0.15s linear; -o-transition: opacity 0.15s linear; transition: opacity 0.15s linear; } .fade.in { opacity: 1; } .collapse { display: none; } .collapse.in { display: block; } tr.collapse.in { display: table-row; } tbody.collapse.in { display: table-row-group; } .collapsing { position: relative; height: 0; overflow: hidden; -webkit-transition-property: height, visibility; -o-transition-property: height, visibility; transition-property: height, visibility; -webkit-transition-duration: 0.35s; -o-transition-duration: 0.35s; transition-duration: 0.35s; -webkit-transition-timing-function: ease; -o-transition-timing-function: ease; transition-timing-function: ease; } .caret { display: inline-block; width: 0; height: 0; margin-left: 2px; vertical-align: middle; border-top: 4px dashed; border-top: 4px solid \9; border-right: 4px solid transparent; border-left: 4px solid transparent; } .dropup, .dropdown { position: relative; } .dropdown-toggle:focus { outline: 0; } .dropdown-menu { position: absolute; top: 100%; left: 0; z-index: 1000; display: none; float: left; min-width: 160px; padding: 5px 0; margin: 2px 0 0; font-size: 14px; text-align: left; list-style: none; background-color: #fff; background-clip: padding-box; border: 1px solid #ccc; border: 1px solid rgba(0, 0, 0, 0.15); border-radius: 4px; -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); } .dropdown-menu.pull-right { right: 0; left: auto; } .dropdown-menu .divider { height: 1px; margin: 9px 0; overflow: hidden; background-color: #e5e5e5; } .dropdown-menu > li > a { display: block; padding: 3px 20px; clear: both; font-weight: 400; line-height: 1.42857143; color: #333333; white-space: nowrap; } .dropdown-menu > li > a:hover, .dropdown-menu > li > a:focus { color: #262626; text-decoration: none; background-color: #f5f5f5; } .dropdown-menu > .active > a, .dropdown-menu > .active > a:hover, .dropdown-menu > .active > a:focus { color: #fff; text-decoration: none; background-color: #337ab7; outline: 0; } .dropdown-menu > .disabled > a, .dropdown-menu > .disabled > a:hover, .dropdown-menu > .disabled > a:focus { color: #777777; } .dropdown-menu > .disabled > a:hover, .dropdown-menu > .disabled > a:focus { text-decoration: none; cursor: not-allowed; background-color: transparent; background-image: none; filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); } .open > .dropdown-menu { display: block; } .open > a { outline: 0; } .dropdown-menu-right { right: 0; left: auto; } .dropdown-menu-left { right: auto; left: 0; } .dropdown-header { display: block; padding: 3px 20px; font-size: 12px; line-height: 1.42857143; color: #777777; white-space: nowrap; } .dropdown-backdrop { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 990; } .pull-right > .dropdown-menu { right: 0; left: auto; } .dropup .caret, .navbar-fixed-bottom .dropdown .caret { content: ""; border-top: 0; border-bottom: 4px dashed; border-bottom: 4px solid \9; } .dropup .dropdown-menu, .navbar-fixed-bottom .dropdown .dropdown-menu { top: auto; bottom: 100%; margin-bottom: 2px; } @media (min-width: 768px) { .navbar-right .dropdown-menu { right: 0; left: auto; } .navbar-right .dropdown-menu-left { right: auto; left: 0; } } .btn-group, .btn-group-vertical { position: relative; display: inline-block; vertical-align: middle; } .btn-group > .btn, .btn-group-vertical > .btn { position: relative; float: left; } .btn-group > .btn:hover, .btn-group-vertical > .btn:hover, .btn-group > .btn:focus, .btn-group-vertical > .btn:focus, .btn-group > .btn:active, .btn-group-vertical > .btn:active, .btn-group > .btn.active, .btn-group-vertical > .btn.active { z-index: 2; } .btn-group .btn + .btn, .btn-group .btn + .btn-group, .btn-group .btn-group + .btn, .btn-group .btn-group + .btn-group { margin-left: -1px; } .btn-toolbar { margin-left: -5px; } .btn-toolbar .btn, .btn-toolbar .btn-group, .btn-toolbar .input-group { float: left; } .btn-toolbar > .btn, .btn-toolbar > .btn-group, .btn-toolbar > .input-group { margin-left: 5px; } .btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { border-radius: 0; } .btn-group > .btn:first-child { margin-left: 0; } .btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { border-top-right-radius: 0; border-bottom-right-radius: 0; } .btn-group > .btn:last-child:not(:first-child), .btn-group > .dropdown-toggle:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; } .btn-group > .btn-group { float: left; } .btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { border-radius: 0; } .btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, .btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { border-top-right-radius: 0; border-bottom-right-radius: 0; } .btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { border-top-left-radius: 0; border-bottom-left-radius: 0; } .btn-group .dropdown-toggle:active, .btn-group.open .dropdown-toggle { outline: 0; } .btn-group > .btn + .dropdown-toggle { padding-right: 8px; padding-left: 8px; } .btn-group > .btn-lg + .dropdown-toggle { padding-right: 12px; padding-left: 12px; } .btn-group.open .dropdown-toggle { -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); } .btn-group.open .dropdown-toggle.btn-link { -webkit-box-shadow: none; box-shadow: none; } .btn .caret { margin-left: 0; } .btn-lg .caret { border-width: 5px 5px 0; border-bottom-width: 0; } .dropup .btn-lg .caret { border-width: 0 5px 5px; } .btn-group-vertical > .btn, .btn-group-vertical > .btn-group, .btn-group-vertical > .btn-group > .btn { display: block; float: none; width: 100%; max-width: 100%; } .btn-group-vertical > .btn-group > .btn { float: none; } .btn-group-vertical > .btn + .btn, .btn-group-vertical > .btn + .btn-group, .btn-group-vertical > .btn-group + .btn, .btn-group-vertical > .btn-group + .btn-group { margin-top: -1px; margin-left: 0; } .btn-group-vertical > .btn:not(:first-child):not(:last-child) { border-radius: 0; } .btn-group-vertical > .btn:first-child:not(:last-child) { border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .btn-group-vertical > .btn:last-child:not(:first-child) { border-top-left-radius: 0; border-top-right-radius: 0; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; } .btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { border-radius: 0; } .btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, .btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { border-top-left-radius: 0; border-top-right-radius: 0; } .btn-group-justified { display: table; width: 100%; table-layout: fixed; border-collapse: separate; } .btn-group-justified > .btn, .btn-group-justified > .btn-group { display: table-cell; float: none; width: 1%; } .btn-group-justified > .btn-group .btn { width: 100%; } .btn-group-justified > .btn-group .dropdown-menu { left: auto; } [data-toggle="buttons"] > .btn input[type="radio"], [data-toggle="buttons"] > .btn-group > .btn input[type="radio"], [data-toggle="buttons"] > .btn input[type="checkbox"], [data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { position: absolute; clip: rect(0, 0, 0, 0); pointer-events: none; } .input-group { position: relative; display: table; border-collapse: separate; } .input-group[class*="col-"] { float: none; padding-right: 0; padding-left: 0; } .input-group .form-control { position: relative; z-index: 2; float: left; width: 100%; margin-bottom: 0; } .input-group .form-control:focus { z-index: 3; } .input-group-lg > .form-control, .input-group-lg > .input-group-addon, .input-group-lg > .input-group-btn > .btn { height: 46px; padding: 10px 16px; font-size: 18px; line-height: 1.3333333; border-radius: 6px; } select.input-group-lg > .form-control, select.input-group-lg > .input-group-addon, select.input-group-lg > .input-group-btn > .btn { height: 46px; line-height: 46px; } textarea.input-group-lg > .form-control, textarea.input-group-lg > .input-group-addon, textarea.input-group-lg > .input-group-btn > .btn, select[multiple].input-group-lg > .form-control, select[multiple].input-group-lg > .input-group-addon, select[multiple].input-group-lg > .input-group-btn > .btn { height: auto; } .input-group-sm > .form-control, .input-group-sm > .input-group-addon, .input-group-sm > .input-group-btn > .btn { height: 30px; padding: 5px 10px; font-size: 12px; line-height: 1.5; border-radius: 3px; } select.input-group-sm > .form-control, select.input-group-sm > .input-group-addon, select.input-group-sm > .input-group-btn > .btn { height: 30px; line-height: 30px; } textarea.input-group-sm > .form-control, textarea.input-group-sm > .input-group-addon, textarea.input-group-sm > .input-group-btn > .btn, select[multiple].input-group-sm > .form-control, select[multiple].input-group-sm > .input-group-addon, select[multiple].input-group-sm > .input-group-btn > .btn { height: auto; } .input-group-addon, .input-group-btn, .input-group .form-control { display: table-cell; } .input-group-addon:not(:first-child):not(:last-child), .input-group-btn:not(:first-child):not(:last-child), .input-group .form-control:not(:first-child):not(:last-child) { border-radius: 0; } .input-group-addon, .input-group-btn { width: 1%; white-space: nowrap; vertical-align: middle; } .input-group-addon { padding: 6px 12px; font-size: 14px; font-weight: 400; line-height: 1; color: #555555; text-align: center; background-color: #eeeeee; border: 1px solid #ccc; border-radius: 4px; } .input-group-addon.input-sm { padding: 5px 10px; font-size: 12px; border-radius: 3px; } .input-group-addon.input-lg { padding: 10px 16px; font-size: 18px; border-radius: 6px; } .input-group-addon input[type="radio"], .input-group-addon input[type="checkbox"] { margin-top: 0; } .input-group .form-control:first-child, .input-group-addon:first-child, .input-group-btn:first-child > .btn, .input-group-btn:first-child > .btn-group > .btn, .input-group-btn:first-child > .dropdown-toggle, .input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), .input-group-btn:last-child > .btn-group:not(:last-child) > .btn { border-top-right-radius: 0; border-bottom-right-radius: 0; } .input-group-addon:first-child { border-right: 0; } .input-group .form-control:last-child, .input-group-addon:last-child, .input-group-btn:last-child > .btn, .input-group-btn:last-child > .btn-group > .btn, .input-group-btn:last-child > .dropdown-toggle, .input-group-btn:first-child > .btn:not(:first-child), .input-group-btn:first-child > .btn-group:not(:first-child) > .btn { border-top-left-radius: 0; border-bottom-left-radius: 0; } .input-group-addon:last-child { border-left: 0; } .input-group-btn { position: relative; font-size: 0; white-space: nowrap; } .input-group-btn > .btn { position: relative; } .input-group-btn > .btn + .btn { margin-left: -1px; } .input-group-btn > .btn:hover, .input-group-btn > .btn:focus, .input-group-btn > .btn:active { z-index: 2; } .input-group-btn:first-child > .btn, .input-group-btn:first-child > .btn-group { margin-right: -1px; } .input-group-btn:last-child > .btn, .input-group-btn:last-child > .btn-group { z-index: 2; margin-left: -1px; } .nav { padding-left: 0; margin-bottom: 0; list-style: none; } .nav > li { position: relative; display: block; } .nav > li > a { position: relative; display: block; padding: 10px 15px; } .nav > li > a:hover, .nav > li > a:focus { text-decoration: none; background-color: #eeeeee; } .nav > li.disabled > a { color: #777777; } .nav > li.disabled > a:hover, .nav > li.disabled > a:focus { color: #777777; text-decoration: none; cursor: not-allowed; background-color: transparent; } .nav .open > a, .nav .open > a:hover, .nav .open > a:focus { background-color: #eeeeee; border-color: #337ab7; } .nav .nav-divider { height: 1px; margin: 9px 0; overflow: hidden; background-color: #e5e5e5; } .nav > li > a > img { max-width: none; } .nav-tabs { border-bottom: 1px solid #ddd; } .nav-tabs > li { float: left; margin-bottom: -1px; } .nav-tabs > li > a { margin-right: 2px; line-height: 1.42857143; border: 1px solid transparent; border-radius: 4px 4px 0 0; } .nav-tabs > li > a:hover { border-color: #eeeeee #eeeeee #ddd; } .nav-tabs > li.active > a, .nav-tabs > li.active > a:hover, .nav-tabs > li.active > a:focus { color: #555555; cursor: default; background-color: #fff; border: 1px solid #ddd; border-bottom-color: transparent; } .nav-tabs.nav-justified { width: 100%; border-bottom: 0; } .nav-tabs.nav-justified > li { float: none; } .nav-tabs.nav-justified > li > a { margin-bottom: 5px; text-align: center; } .nav-tabs.nav-justified > .dropdown .dropdown-menu { top: auto; left: auto; } @media (min-width: 768px) { .nav-tabs.nav-justified > li { display: table-cell; width: 1%; } .nav-tabs.nav-justified > li > a { margin-bottom: 0; } } .nav-tabs.nav-justified > li > a { margin-right: 0; border-radius: 4px; } .nav-tabs.nav-justified > .active > a, .nav-tabs.nav-justified > .active > a:hover, .nav-tabs.nav-justified > .active > a:focus { border: 1px solid #ddd; } @media (min-width: 768px) { .nav-tabs.nav-justified > li > a { border-bottom: 1px solid #ddd; border-radius: 4px 4px 0 0; } .nav-tabs.nav-justified > .active > a, .nav-tabs.nav-justified > .active > a:hover, .nav-tabs.nav-justified > .active > a:focus { border-bottom-color: #fff; } } .nav-pills > li { float: left; } .nav-pills > li > a { border-radius: 4px; } .nav-pills > li + li { margin-left: 2px; } .nav-pills > li.active > a, .nav-pills > li.active > a:hover, .nav-pills > li.active > a:focus { color: #fff; background-color: #337ab7; } .nav-stacked > li { float: none; } .nav-stacked > li + li { margin-top: 2px; margin-left: 0; } .nav-justified { width: 100%; } .nav-justified > li { float: none; } .nav-justified > li > a { margin-bottom: 5px; text-align: center; } .nav-justified > .dropdown .dropdown-menu { top: auto; left: auto; } @media (min-width: 768px) { .nav-justified > li { display: table-cell; width: 1%; } .nav-justified > li > a { margin-bottom: 0; } } .nav-tabs-justified { border-bottom: 0; } .nav-tabs-justified > li > a { margin-right: 0; border-radius: 4px; } .nav-tabs-justified > .active > a, .nav-tabs-justified > .active > a:hover, .nav-tabs-justified > .active > a:focus { border: 1px solid #ddd; } @media (min-width: 768px) { .nav-tabs-justified > li > a { border-bottom: 1px solid #ddd; border-radius: 4px 4px 0 0; } .nav-tabs-justified > .active > a, .nav-tabs-justified > .active > a:hover, .nav-tabs-justified > .active > a:focus { border-bottom-color: #fff; } } .tab-content > .tab-pane { display: none; } .tab-content > .active { display: block; } .nav-tabs .dropdown-menu { margin-top: -1px; border-top-left-radius: 0; border-top-right-radius: 0; } .navbar { position: relative; min-height: 50px; margin-bottom: 20px; border: 1px solid transparent; } @media (min-width: 768px) { .navbar { border-radius: 4px; } } @media (min-width: 768px) { .navbar-header { float: left; } } .navbar-collapse { padding-right: 15px; padding-left: 15px; overflow-x: visible; border-top: 1px solid transparent; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); -webkit-overflow-scrolling: touch; } .navbar-collapse.in { overflow-y: auto; } @media (min-width: 768px) { .navbar-collapse { width: auto; border-top: 0; -webkit-box-shadow: none; box-shadow: none; } .navbar-collapse.collapse { display: block !important; height: auto !important; padding-bottom: 0; overflow: visible !important; } .navbar-collapse.in { overflow-y: visible; } .navbar-fixed-top .navbar-collapse, .navbar-static-top .navbar-collapse, .navbar-fixed-bottom .navbar-collapse { padding-right: 0; padding-left: 0; } } .navbar-fixed-top, .navbar-fixed-bottom { position: fixed; right: 0; left: 0; z-index: 1030; } .navbar-fixed-top .navbar-collapse, .navbar-fixed-bottom .navbar-collapse { max-height: 340px; } @media (max-device-width: 480px) and (orientation: landscape) { .navbar-fixed-top .navbar-collapse, .navbar-fixed-bottom .navbar-collapse { max-height: 200px; } } @media (min-width: 768px) { .navbar-fixed-top, .navbar-fixed-bottom { border-radius: 0; } } .navbar-fixed-top { top: 0; border-width: 0 0 1px; } .navbar-fixed-bottom { bottom: 0; margin-bottom: 0; border-width: 1px 0 0; } .container > .navbar-header, .container-fluid > .navbar-header, .container > .navbar-collapse, .container-fluid > .navbar-collapse { margin-right: -15px; margin-left: -15px; } @media (min-width: 768px) { .container > .navbar-header, .container-fluid > .navbar-header, .container > .navbar-collapse, .container-fluid > .navbar-collapse { margin-right: 0; margin-left: 0; } } .navbar-static-top { z-index: 1000; border-width: 0 0 1px; } @media (min-width: 768px) { .navbar-static-top { border-radius: 0; } } .navbar-brand { float: left; height: 50px; padding: 15px 15px; font-size: 18px; line-height: 20px; } .navbar-brand:hover, .navbar-brand:focus { text-decoration: none; } .navbar-brand > img { display: block; } @media (min-width: 768px) { .navbar > .container .navbar-brand, .navbar > .container-fluid .navbar-brand { margin-left: -15px; } } .navbar-toggle { position: relative; float: right; padding: 9px 10px; margin-right: 15px; margin-top: 8px; margin-bottom: 8px; background-color: transparent; background-image: none; border: 1px solid transparent; border-radius: 4px; } .navbar-toggle:focus { outline: 0; } .navbar-toggle .icon-bar { display: block; width: 22px; height: 2px; border-radius: 1px; } .navbar-toggle .icon-bar + .icon-bar { margin-top: 4px; } @media (min-width: 768px) { .navbar-toggle { display: none; } } .navbar-nav { margin: 7.5px -15px; } .navbar-nav > li > a { padding-top: 10px; padding-bottom: 10px; line-height: 20px; } @media (max-width: 767px) { .navbar-nav .open .dropdown-menu { position: static; float: none; width: auto; margin-top: 0; background-color: transparent; border: 0; -webkit-box-shadow: none; box-shadow: none; } .navbar-nav .open .dropdown-menu > li > a, .navbar-nav .open .dropdown-menu .dropdown-header { padding: 5px 15px 5px 25px; } .navbar-nav .open .dropdown-menu > li > a { line-height: 20px; } .navbar-nav .open .dropdown-menu > li > a:hover, .navbar-nav .open .dropdown-menu > li > a:focus { background-image: none; } } @media (min-width: 768px) { .navbar-nav { float: left; margin: 0; } .navbar-nav > li { float: left; } .navbar-nav > li > a { padding-top: 15px; padding-bottom: 15px; } } .navbar-form { padding: 10px 15px; margin-right: -15px; margin-left: -15px; border-top: 1px solid transparent; border-bottom: 1px solid transparent; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); margin-top: 8px; margin-bottom: 8px; } @media (min-width: 768px) { .navbar-form .form-group { display: inline-block; margin-bottom: 0; vertical-align: middle; } .navbar-form .form-control { display: inline-block; width: auto; vertical-align: middle; } .navbar-form .form-control-static { display: inline-block; } .navbar-form .input-group { display: inline-table; vertical-align: middle; } .navbar-form .input-group .input-group-addon, .navbar-form .input-group .input-group-btn, .navbar-form .input-group .form-control { width: auto; } .navbar-form .input-group > .form-control { width: 100%; } .navbar-form .control-label { margin-bottom: 0; vertical-align: middle; } .navbar-form .radio, .navbar-form .checkbox { display: inline-block; margin-top: 0; margin-bottom: 0; vertical-align: middle; } .navbar-form .radio label, .navbar-form .checkbox label { padding-left: 0; } .navbar-form .radio input[type="radio"], .navbar-form .checkbox input[type="checkbox"] { position: relative; margin-left: 0; } .navbar-form .has-feedback .form-control-feedback { top: 0; } } @media (max-width: 767px) { .navbar-form .form-group { margin-bottom: 5px; } .navbar-form .form-group:last-child { margin-bottom: 0; } } @media (min-width: 768px) { .navbar-form { width: auto; padding-top: 0; padding-bottom: 0; margin-right: 0; margin-left: 0; border: 0; -webkit-box-shadow: none; box-shadow: none; } } .navbar-nav > li > .dropdown-menu { margin-top: 0; border-top-left-radius: 0; border-top-right-radius: 0; } .navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { margin-bottom: 0; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .navbar-btn { margin-top: 8px; margin-bottom: 8px; } .navbar-btn.btn-sm { margin-top: 10px; margin-bottom: 10px; } .navbar-btn.btn-xs { margin-top: 14px; margin-bottom: 14px; } .navbar-text { margin-top: 15px; margin-bottom: 15px; } @media (min-width: 768px) { .navbar-text { float: left; margin-right: 15px; margin-left: 15px; } } @media (min-width: 768px) { .navbar-left { float: left !important; } .navbar-right { float: right !important; margin-right: -15px; } .navbar-right ~ .navbar-right { margin-right: 0; } } .navbar-default { background-color: #f8f8f8; border-color: #e7e7e7; } .navbar-default .navbar-brand { color: #777; } .navbar-default .navbar-brand:hover, .navbar-default .navbar-brand:focus { color: #5e5e5e; background-color: transparent; } .navbar-default .navbar-text { color: #777; } .navbar-default .navbar-nav > li > a { color: #777; } .navbar-default .navbar-nav > li > a:hover, .navbar-default .navbar-nav > li > a:focus { color: #333; background-color: transparent; } .navbar-default .navbar-nav > .active > a, .navbar-default .navbar-nav > .active > a:hover, .navbar-default .navbar-nav > .active > a:focus { color: #555; background-color: #e7e7e7; } .navbar-default .navbar-nav > .disabled > a, .navbar-default .navbar-nav > .disabled > a:hover, .navbar-default .navbar-nav > .disabled > a:focus { color: #ccc; background-color: transparent; } .navbar-default .navbar-nav > .open > a, .navbar-default .navbar-nav > .open > a:hover, .navbar-default .navbar-nav > .open > a:focus { color: #555; background-color: #e7e7e7; } @media (max-width: 767px) { .navbar-default .navbar-nav .open .dropdown-menu > li > a { color: #777; } .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { color: #333; background-color: transparent; } .navbar-default .navbar-nav .open .dropdown-menu > .active > a, .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { color: #555; background-color: #e7e7e7; } .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { color: #ccc; background-color: transparent; } } .navbar-default .navbar-toggle { border-color: #ddd; } .navbar-default .navbar-toggle:hover, .navbar-default .navbar-toggle:focus { background-color: #ddd; } .navbar-default .navbar-toggle .icon-bar { background-color: #888; } .navbar-default .navbar-collapse, .navbar-default .navbar-form { border-color: #e7e7e7; } .navbar-default .navbar-link { color: #777; } .navbar-default .navbar-link:hover { color: #333; } .navbar-default .btn-link { color: #777; } .navbar-default .btn-link:hover, .navbar-default .btn-link:focus { color: #333; } .navbar-default .btn-link[disabled]:hover, fieldset[disabled] .navbar-default .btn-link:hover, .navbar-default .btn-link[disabled]:focus, fieldset[disabled] .navbar-default .btn-link:focus { color: #ccc; } .navbar-inverse { background-color: #222; border-color: #080808; } .navbar-inverse .navbar-brand { color: #9d9d9d; } .navbar-inverse .navbar-brand:hover, .navbar-inverse .navbar-brand:focus { color: #fff; background-color: transparent; } .navbar-inverse .navbar-text { color: #9d9d9d; } .navbar-inverse .navbar-nav > li > a { color: #9d9d9d; } .navbar-inverse .navbar-nav > li > a:hover, .navbar-inverse .navbar-nav > li > a:focus { color: #fff; background-color: transparent; } .navbar-inverse .navbar-nav > .active > a, .navbar-inverse .navbar-nav > .active > a:hover, .navbar-inverse .navbar-nav > .active > a:focus { color: #fff; background-color: #080808; } .navbar-inverse .navbar-nav > .disabled > a, .navbar-inverse .navbar-nav > .disabled > a:hover, .navbar-inverse .navbar-nav > .disabled > a:focus { color: #444; background-color: transparent; } .navbar-inverse .navbar-nav > .open > a, .navbar-inverse .navbar-nav > .open > a:hover, .navbar-inverse .navbar-nav > .open > a:focus { color: #fff; background-color: #080808; } @media (max-width: 767px) { .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { border-color: #080808; } .navbar-inverse .navbar-nav .open .dropdown-menu .divider { background-color: #080808; } .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { color: #9d9d9d; } .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { color: #fff; background-color: transparent; } .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { color: #fff; background-color: #080808; } .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { color: #444; background-color: transparent; } } .navbar-inverse .navbar-toggle { border-color: #333; } .navbar-inverse .navbar-toggle:hover, .navbar-inverse .navbar-toggle:focus { background-color: #333; } .navbar-inverse .navbar-toggle .icon-bar { background-color: #fff; } .navbar-inverse .navbar-collapse, .navbar-inverse .navbar-form { border-color: #101010; } .navbar-inverse .navbar-link { color: #9d9d9d; } .navbar-inverse .navbar-link:hover { color: #fff; } .navbar-inverse .btn-link { color: #9d9d9d; } .navbar-inverse .btn-link:hover, .navbar-inverse .btn-link:focus { color: #fff; } .navbar-inverse .btn-link[disabled]:hover, fieldset[disabled] .navbar-inverse .btn-link:hover, .navbar-inverse .btn-link[disabled]:focus, fieldset[disabled] .navbar-inverse .btn-link:focus { color: #444; } .breadcrumb { padding: 8px 15px; margin-bottom: 20px; list-style: none; background-color: #f5f5f5; border-radius: 4px; } .breadcrumb > li { display: inline-block; } .breadcrumb > li + li:before { padding: 0 5px; color: #ccc; content: "/\00a0"; } .breadcrumb > .active { color: #777777; } .pagination { display: inline-block; padding-left: 0; margin: 20px 0; border-radius: 4px; } .pagination > li { display: inline; } .pagination > li > a, .pagination > li > span { position: relative; float: left; padding: 6px 12px; margin-left: -1px; line-height: 1.42857143; color: #337ab7; text-decoration: none; background-color: #fff; border: 1px solid #ddd; } .pagination > li > a:hover, .pagination > li > span:hover, .pagination > li > a:focus, .pagination > li > span:focus { z-index: 2; color: #23527c; background-color: #eeeeee; border-color: #ddd; } .pagination > li:first-child > a, .pagination > li:first-child > span { margin-left: 0; border-top-left-radius: 4px; border-bottom-left-radius: 4px; } .pagination > li:last-child > a, .pagination > li:last-child > span { border-top-right-radius: 4px; border-bottom-right-radius: 4px; } .pagination > .active > a, .pagination > .active > span, .pagination > .active > a:hover, .pagination > .active > span:hover, .pagination > .active > a:focus, .pagination > .active > span:focus { z-index: 3; color: #fff; cursor: default; background-color: #337ab7; border-color: #337ab7; } .pagination > .disabled > span, .pagination > .disabled > span:hover, .pagination > .disabled > span:focus, .pagination > .disabled > a, .pagination > .disabled > a:hover, .pagination > .disabled > a:focus { color: #777777; cursor: not-allowed; background-color: #fff; border-color: #ddd; } .pagination-lg > li > a, .pagination-lg > li > span { padding: 10px 16px; font-size: 18px; line-height: 1.3333333; } .pagination-lg > li:first-child > a, .pagination-lg > li:first-child > span { border-top-left-radius: 6px; border-bottom-left-radius: 6px; } .pagination-lg > li:last-child > a, .pagination-lg > li:last-child > span { border-top-right-radius: 6px; border-bottom-right-radius: 6px; } .pagination-sm > li > a, .pagination-sm > li > span { padding: 5px 10px; font-size: 12px; line-height: 1.5; } .pagination-sm > li:first-child > a, .pagination-sm > li:first-child > span { border-top-left-radius: 3px; border-bottom-left-radius: 3px; } .pagination-sm > li:last-child > a, .pagination-sm > li:last-child > span { border-top-right-radius: 3px; border-bottom-right-radius: 3px; } .pager { padding-left: 0; margin: 20px 0; text-align: center; list-style: none; } .pager li { display: inline; } .pager li > a, .pager li > span { display: inline-block; padding: 5px 14px; background-color: #fff; border: 1px solid #ddd; border-radius: 15px; } .pager li > a:hover, .pager li > a:focus { text-decoration: none; background-color: #eeeeee; } .pager .next > a, .pager .next > span { float: right; } .pager .previous > a, .pager .previous > span { float: left; } .pager .disabled > a, .pager .disabled > a:hover, .pager .disabled > a:focus, .pager .disabled > span { color: #777777; cursor: not-allowed; background-color: #fff; } .label { display: inline; padding: 0.2em 0.6em 0.3em; font-size: 75%; font-weight: 700; line-height: 1; color: #fff; text-align: center; white-space: nowrap; vertical-align: baseline; border-radius: 0.25em; } a.label:hover, a.label:focus { color: #fff; text-decoration: none; cursor: pointer; } .label:empty { display: none; } .btn .label { position: relative; top: -1px; } .label-default { background-color: #777777; } .label-default[href]:hover, .label-default[href]:focus { background-color: #5e5e5e; } .label-primary { background-color: #337ab7; } .label-primary[href]:hover, .label-primary[href]:focus { background-color: #286090; } .label-success { background-color: #5cb85c; } .label-success[href]:hover, .label-success[href]:focus { background-color: #449d44; } .label-info { background-color: #5bc0de; } .label-info[href]:hover, .label-info[href]:focus { background-color: #31b0d5; } .label-warning { background-color: #f0ad4e; } .label-warning[href]:hover, .label-warning[href]:focus { background-color: #ec971f; } .label-danger { background-color: #d9534f; } .label-danger[href]:hover, .label-danger[href]:focus { background-color: #c9302c; } .badge { display: inline-block; min-width: 10px; padding: 3px 7px; font-size: 12px; font-weight: bold; line-height: 1; color: #fff; text-align: center; white-space: nowrap; vertical-align: middle; background-color: #777777; border-radius: 10px; } .badge:empty { display: none; } .btn .badge { position: relative; top: -1px; } .btn-xs .badge, .btn-group-xs > .btn .badge { top: 0; padding: 1px 5px; } a.badge:hover, a.badge:focus { color: #fff; text-decoration: none; cursor: pointer; } .list-group-item.active > .badge, .nav-pills > .active > a > .badge { color: #337ab7; background-color: #fff; } .list-group-item > .badge { float: right; } .list-group-item > .badge + .badge { margin-right: 5px; } .nav-pills > li > a > .badge { margin-left: 3px; } .jumbotron { padding-top: 30px; padding-bottom: 30px; margin-bottom: 30px; color: inherit; background-color: #eeeeee; } .jumbotron h1, .jumbotron .h1 { color: inherit; } .jumbotron p { margin-bottom: 15px; font-size: 21px; font-weight: 200; } .jumbotron > hr { border-top-color: #d5d5d5; } .container .jumbotron, .container-fluid .jumbotron { padding-right: 15px; padding-left: 15px; border-radius: 6px; } .jumbotron .container { max-width: 100%; } @media screen and (min-width: 768px) { .jumbotron { padding-top: 48px; padding-bottom: 48px; } .container .jumbotron, .container-fluid .jumbotron { padding-right: 60px; padding-left: 60px; } .jumbotron h1, .jumbotron .h1 { font-size: 63px; } } .thumbnail { display: block; padding: 4px; margin-bottom: 20px; line-height: 1.42857143; background-color: #fff; border: 1px solid #ddd; border-radius: 4px; -webkit-transition: border 0.2s ease-in-out; -o-transition: border 0.2s ease-in-out; transition: border 0.2s ease-in-out; } .thumbnail > img, .thumbnail a > img { margin-right: auto; margin-left: auto; } a.thumbnail:hover, a.thumbnail:focus, a.thumbnail.active { border-color: #337ab7; } .thumbnail .caption { padding: 9px; color: #333333; } .alert { padding: 15px; margin-bottom: 20px; border: 1px solid transparent; border-radius: 4px; } .alert h4 { margin-top: 0; color: inherit; } .alert .alert-link { font-weight: bold; } .alert > p, .alert > ul { margin-bottom: 0; } .alert > p + p { margin-top: 5px; } .alert-dismissable, .alert-dismissible { padding-right: 35px; } .alert-dismissable .close, .alert-dismissible .close { position: relative; top: -2px; right: -21px; color: inherit; } .alert-success { color: #3c763d; background-color: #dff0d8; border-color: #d6e9c6; } .alert-success hr { border-top-color: #c9e2b3; } .alert-success .alert-link { color: #2b542c; } .alert-info { color: #31708f; background-color: #d9edf7; border-color: #bce8f1; } .alert-info hr { border-top-color: #a6e1ec; } .alert-info .alert-link { color: #245269; } .alert-warning { color: #8a6d3b; background-color: #fcf8e3; border-color: #faebcc; } .alert-warning hr { border-top-color: #f7e1b5; } .alert-warning .alert-link { color: #66512c; } .alert-danger { color: #a94442; background-color: #f2dede; border-color: #ebccd1; } .alert-danger hr { border-top-color: #e4b9c0; } .alert-danger .alert-link { color: #843534; } @-webkit-keyframes progress-bar-stripes { from { background-position: 40px 0; } to { background-position: 0 0; } } @-o-keyframes progress-bar-stripes { from { background-position: 40px 0; } to { background-position: 0 0; } } @keyframes progress-bar-stripes { from { background-position: 40px 0; } to { background-position: 0 0; } } .progress { height: 20px; margin-bottom: 20px; overflow: hidden; background-color: #f5f5f5; border-radius: 4px; -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); } .progress-bar { float: left; width: 0%; height: 100%; font-size: 12px; line-height: 20px; color: #fff; text-align: center; background-color: #337ab7; -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); -webkit-transition: width 0.6s ease; -o-transition: width 0.6s ease; transition: width 0.6s ease; } .progress-striped .progress-bar, .progress-bar-striped { background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -webkit-background-size: 40px 40px; background-size: 40px 40px; } .progress.active .progress-bar, .progress-bar.active { -webkit-animation: progress-bar-stripes 2s linear infinite; -o-animation: progress-bar-stripes 2s linear infinite; animation: progress-bar-stripes 2s linear infinite; } .progress-bar-success { background-color: #5cb85c; } .progress-striped .progress-bar-success { background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .progress-bar-info { background-color: #5bc0de; } .progress-striped .progress-bar-info { background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .progress-bar-warning { background-color: #f0ad4e; } .progress-striped .progress-bar-warning { background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .progress-bar-danger { background-color: #d9534f; } .progress-striped .progress-bar-danger { background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .media { margin-top: 15px; } .media:first-child { margin-top: 0; } .media, .media-body { overflow: hidden; zoom: 1; } .media-body { width: 10000px; } .media-object { display: block; } .media-object.img-thumbnail { max-width: none; } .media-right, .media > .pull-right { padding-left: 10px; } .media-left, .media > .pull-left { padding-right: 10px; } .media-left, .media-right, .media-body { display: table-cell; vertical-align: top; } .media-middle { vertical-align: middle; } .media-bottom { vertical-align: bottom; } .media-heading { margin-top: 0; margin-bottom: 5px; } .media-list { padding-left: 0; list-style: none; } .list-group { padding-left: 0; margin-bottom: 20px; } .list-group-item { position: relative; display: block; padding: 10px 15px; margin-bottom: -1px; background-color: #fff; border: 1px solid #ddd; } .list-group-item:first-child { border-top-left-radius: 4px; border-top-right-radius: 4px; } .list-group-item:last-child { margin-bottom: 0; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; } .list-group-item.disabled, .list-group-item.disabled:hover, .list-group-item.disabled:focus { color: #777777; cursor: not-allowed; background-color: #eeeeee; } .list-group-item.disabled .list-group-item-heading, .list-group-item.disabled:hover .list-group-item-heading, .list-group-item.disabled:focus .list-group-item-heading { color: inherit; } .list-group-item.disabled .list-group-item-text, .list-group-item.disabled:hover .list-group-item-text, .list-group-item.disabled:focus .list-group-item-text { color: #777777; } .list-group-item.active, .list-group-item.active:hover, .list-group-item.active:focus { z-index: 2; color: #fff; background-color: #337ab7; border-color: #337ab7; } .list-group-item.active .list-group-item-heading, .list-group-item.active:hover .list-group-item-heading, .list-group-item.active:focus .list-group-item-heading, .list-group-item.active .list-group-item-heading > small, .list-group-item.active:hover .list-group-item-heading > small, .list-group-item.active:focus .list-group-item-heading > small, .list-group-item.active .list-group-item-heading > .small, .list-group-item.active:hover .list-group-item-heading > .small, .list-group-item.active:focus .list-group-item-heading > .small { color: inherit; } .list-group-item.active .list-group-item-text, .list-group-item.active:hover .list-group-item-text, .list-group-item.active:focus .list-group-item-text { color: #c7ddef; } a.list-group-item, button.list-group-item { color: #555; } a.list-group-item .list-group-item-heading, button.list-group-item .list-group-item-heading { color: #333; } a.list-group-item:hover, button.list-group-item:hover, a.list-group-item:focus, button.list-group-item:focus { color: #555; text-decoration: none; background-color: #f5f5f5; } button.list-group-item { width: 100%; text-align: left; } .list-group-item-success { color: #3c763d; background-color: #dff0d8; } a.list-group-item-success, button.list-group-item-success { color: #3c763d; } a.list-group-item-success .list-group-item-heading, button.list-group-item-success .list-group-item-heading { color: inherit; } a.list-group-item-success:hover, button.list-group-item-success:hover, a.list-group-item-success:focus, button.list-group-item-success:focus { color: #3c763d; background-color: #d0e9c6; } a.list-group-item-success.active, button.list-group-item-success.active, a.list-group-item-success.active:hover, button.list-group-item-success.active:hover, a.list-group-item-success.active:focus, button.list-group-item-success.active:focus { color: #fff; background-color: #3c763d; border-color: #3c763d; } .list-group-item-info { color: #31708f; background-color: #d9edf7; } a.list-group-item-info, button.list-group-item-info { color: #31708f; } a.list-group-item-info .list-group-item-heading, button.list-group-item-info .list-group-item-heading { color: inherit; } a.list-group-item-info:hover, button.list-group-item-info:hover, a.list-group-item-info:focus, button.list-group-item-info:focus { color: #31708f; background-color: #c4e3f3; } a.list-group-item-info.active, button.list-group-item-info.active, a.list-group-item-info.active:hover, button.list-group-item-info.active:hover, a.list-group-item-info.active:focus, button.list-group-item-info.active:focus { color: #fff; background-color: #31708f; border-color: #31708f; } .list-group-item-warning { color: #8a6d3b; background-color: #fcf8e3; } a.list-group-item-warning, button.list-group-item-warning { color: #8a6d3b; } a.list-group-item-warning .list-group-item-heading, button.list-group-item-warning .list-group-item-heading { color: inherit; } a.list-group-item-warning:hover, button.list-group-item-warning:hover, a.list-group-item-warning:focus, button.list-group-item-warning:focus { color: #8a6d3b; background-color: #faf2cc; } a.list-group-item-warning.active, button.list-group-item-warning.active, a.list-group-item-warning.active:hover, button.list-group-item-warning.active:hover, a.list-group-item-warning.active:focus, button.list-group-item-warning.active:focus { color: #fff; background-color: #8a6d3b; border-color: #8a6d3b; } .list-group-item-danger { color: #a94442; background-color: #f2dede; } a.list-group-item-danger, button.list-group-item-danger { color: #a94442; } a.list-group-item-danger .list-group-item-heading, button.list-group-item-danger .list-group-item-heading { color: inherit; } a.list-group-item-danger:hover, button.list-group-item-danger:hover, a.list-group-item-danger:focus, button.list-group-item-danger:focus { color: #a94442; background-color: #ebcccc; } a.list-group-item-danger.active, button.list-group-item-danger.active, a.list-group-item-danger.active:hover, button.list-group-item-danger.active:hover, a.list-group-item-danger.active:focus, button.list-group-item-danger.active:focus { color: #fff; background-color: #a94442; border-color: #a94442; } .list-group-item-heading { margin-top: 0; margin-bottom: 5px; } .list-group-item-text { margin-bottom: 0; line-height: 1.3; } .panel { margin-bottom: 20px; background-color: #fff; border: 1px solid transparent; border-radius: 4px; -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); } .panel-body { padding: 15px; } .panel-heading { padding: 10px 15px; border-bottom: 1px solid transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; } .panel-heading > .dropdown .dropdown-toggle { color: inherit; } .panel-title { margin-top: 0; margin-bottom: 0; font-size: 16px; color: inherit; } .panel-title > a, .panel-title > small, .panel-title > .small, .panel-title > small > a, .panel-title > .small > a { color: inherit; } .panel-footer { padding: 10px 15px; background-color: #f5f5f5; border-top: 1px solid #ddd; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; } .panel > .list-group, .panel > .panel-collapse > .list-group { margin-bottom: 0; } .panel > .list-group .list-group-item, .panel > .panel-collapse > .list-group .list-group-item { border-width: 1px 0; border-radius: 0; } .panel > .list-group:first-child .list-group-item:first-child, .panel > .panel-collapse > .list-group:first-child .list-group-item:first-child { border-top: 0; border-top-left-radius: 3px; border-top-right-radius: 3px; } .panel > .list-group:last-child .list-group-item:last-child, .panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { border-bottom: 0; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; } .panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child { border-top-left-radius: 0; border-top-right-radius: 0; } .panel-heading + .list-group .list-group-item:first-child { border-top-width: 0; } .list-group + .panel-footer { border-top-width: 0; } .panel > .table, .panel > .table-responsive > .table, .panel > .panel-collapse > .table { margin-bottom: 0; } .panel > .table caption, .panel > .table-responsive > .table caption, .panel > .panel-collapse > .table caption { padding-right: 15px; padding-left: 15px; } .panel > .table:first-child, .panel > .table-responsive:first-child > .table:first-child { border-top-left-radius: 3px; border-top-right-radius: 3px; } .panel > .table:first-child > thead:first-child > tr:first-child, .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, .panel > .table:first-child > tbody:first-child > tr:first-child, .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { border-top-left-radius: 3px; border-top-right-radius: 3px; } .panel > .table:first-child > thead:first-child > tr:first-child td:first-child, .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, .panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, .panel > .table:first-child > thead:first-child > tr:first-child th:first-child, .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, .panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { border-top-left-radius: 3px; } .panel > .table:first-child > thead:first-child > tr:first-child td:last-child, .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, .panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, .panel > .table:first-child > thead:first-child > tr:first-child th:last-child, .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, .panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { border-top-right-radius: 3px; } .panel > .table:last-child, .panel > .table-responsive:last-child > .table:last-child { border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; } .panel > .table:last-child > tbody:last-child > tr:last-child, .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, .panel > .table:last-child > tfoot:last-child > tr:last-child, .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; } .panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, .panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, .panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, .panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { border-bottom-left-radius: 3px; } .panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, .panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, .panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, .panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { border-bottom-right-radius: 3px; } .panel > .panel-body + .table, .panel > .panel-body + .table-responsive, .panel > .table + .panel-body, .panel > .table-responsive + .panel-body { border-top: 1px solid #ddd; } .panel > .table > tbody:first-child > tr:first-child th, .panel > .table > tbody:first-child > tr:first-child td { border-top: 0; } .panel > .table-bordered, .panel > .table-responsive > .table-bordered { border: 0; } .panel > .table-bordered > thead > tr > th:first-child, .panel > .table-responsive > .table-bordered > thead > tr > th:first-child, .panel > .table-bordered > tbody > tr > th:first-child, .panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, .panel > .table-bordered > tfoot > tr > th:first-child, .panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, .panel > .table-bordered > thead > tr > td:first-child, .panel > .table-responsive > .table-bordered > thead > tr > td:first-child, .panel > .table-bordered > tbody > tr > td:first-child, .panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, .panel > .table-bordered > tfoot > tr > td:first-child, .panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { border-left: 0; } .panel > .table-bordered > thead > tr > th:last-child, .panel > .table-responsive > .table-bordered > thead > tr > th:last-child, .panel > .table-bordered > tbody > tr > th:last-child, .panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, .panel > .table-bordered > tfoot > tr > th:last-child, .panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, .panel > .table-bordered > thead > tr > td:last-child, .panel > .table-responsive > .table-bordered > thead > tr > td:last-child, .panel > .table-bordered > tbody > tr > td:last-child, .panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, .panel > .table-bordered > tfoot > tr > td:last-child, .panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { border-right: 0; } .panel > .table-bordered > thead > tr:first-child > td, .panel > .table-responsive > .table-bordered > thead > tr:first-child > td, .panel > .table-bordered > tbody > tr:first-child > td, .panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, .panel > .table-bordered > thead > tr:first-child > th, .panel > .table-responsive > .table-bordered > thead > tr:first-child > th, .panel > .table-bordered > tbody > tr:first-child > th, .panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { border-bottom: 0; } .panel > .table-bordered > tbody > tr:last-child > td, .panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, .panel > .table-bordered > tfoot > tr:last-child > td, .panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, .panel > .table-bordered > tbody > tr:last-child > th, .panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, .panel > .table-bordered > tfoot > tr:last-child > th, .panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { border-bottom: 0; } .panel > .table-responsive { margin-bottom: 0; border: 0; } .panel-group { margin-bottom: 20px; } .panel-group .panel { margin-bottom: 0; border-radius: 4px; } .panel-group .panel + .panel { margin-top: 5px; } .panel-group .panel-heading { border-bottom: 0; } .panel-group .panel-heading + .panel-collapse > .panel-body, .panel-group .panel-heading + .panel-collapse > .list-group { border-top: 1px solid #ddd; } .panel-group .panel-footer { border-top: 0; } .panel-group .panel-footer + .panel-collapse .panel-body { border-bottom: 1px solid #ddd; } .panel-default { border-color: #ddd; } .panel-default > .panel-heading { color: #333333; background-color: #f5f5f5; border-color: #ddd; } .panel-default > .panel-heading + .panel-collapse > .panel-body { border-top-color: #ddd; } .panel-default > .panel-heading .badge { color: #f5f5f5; background-color: #333333; } .panel-default > .panel-footer + .panel-collapse > .panel-body { border-bottom-color: #ddd; } .panel-primary { border-color: #337ab7; } .panel-primary > .panel-heading { color: #fff; background-color: #337ab7; border-color: #337ab7; } .panel-primary > .panel-heading + .panel-collapse > .panel-body { border-top-color: #337ab7; } .panel-primary > .panel-heading .badge { color: #337ab7; background-color: #fff; } .panel-primary > .panel-footer + .panel-collapse > .panel-body { border-bottom-color: #337ab7; } .panel-success { border-color: #d6e9c6; } .panel-success > .panel-heading { color: #3c763d; background-color: #dff0d8; border-color: #d6e9c6; } .panel-success > .panel-heading + .panel-collapse > .panel-body { border-top-color: #d6e9c6; } .panel-success > .panel-heading .badge { color: #dff0d8; background-color: #3c763d; } .panel-success > .panel-footer + .panel-collapse > .panel-body { border-bottom-color: #d6e9c6; } .panel-info { border-color: #bce8f1; } .panel-info > .panel-heading { color: #31708f; background-color: #d9edf7; border-color: #bce8f1; } .panel-info > .panel-heading + .panel-collapse > .panel-body { border-top-color: #bce8f1; } .panel-info > .panel-heading .badge { color: #d9edf7; background-color: #31708f; } .panel-info > .panel-footer + .panel-collapse > .panel-body { border-bottom-color: #bce8f1; } .panel-warning { border-color: #faebcc; } .panel-warning > .panel-heading { color: #8a6d3b; background-color: #fcf8e3; border-color: #faebcc; } .panel-warning > .panel-heading + .panel-collapse > .panel-body { border-top-color: #faebcc; } .panel-warning > .panel-heading .badge { color: #fcf8e3; background-color: #8a6d3b; } .panel-warning > .panel-footer + .panel-collapse > .panel-body { border-bottom-color: #faebcc; } .panel-danger { border-color: #ebccd1; } .panel-danger > .panel-heading { color: #a94442; background-color: #f2dede; border-color: #ebccd1; } .panel-danger > .panel-heading + .panel-collapse > .panel-body { border-top-color: #ebccd1; } .panel-danger > .panel-heading .badge { color: #f2dede; background-color: #a94442; } .panel-danger > .panel-footer + .panel-collapse > .panel-body { border-bottom-color: #ebccd1; } .embed-responsive { position: relative; display: block; height: 0; padding: 0; overflow: hidden; } .embed-responsive .embed-responsive-item, .embed-responsive iframe, .embed-responsive embed, .embed-responsive object, .embed-responsive video { position: absolute; top: 0; bottom: 0; left: 0; width: 100%; height: 100%; border: 0; } .embed-responsive-16by9 { padding-bottom: 56.25%; } .embed-responsive-4by3 { padding-bottom: 75%; } .well { min-height: 20px; padding: 19px; margin-bottom: 20px; background-color: #f5f5f5; border: 1px solid #e3e3e3; border-radius: 4px; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); } .well blockquote { border-color: #ddd; border-color: rgba(0, 0, 0, 0.15); } .well-lg { padding: 24px; border-radius: 6px; } .well-sm { padding: 9px; border-radius: 3px; } .close { float: right; font-size: 21px; font-weight: bold; line-height: 1; color: #000; text-shadow: 0 1px 0 #fff; filter: alpha(opacity=20); opacity: 0.2; } .close:hover, .close:focus { color: #000; text-decoration: none; cursor: pointer; filter: alpha(opacity=50); opacity: 0.5; } button.close { padding: 0; cursor: pointer; background: transparent; border: 0; -webkit-appearance: none; -moz-appearance: none; appearance: none; } .modal-open { overflow: hidden; } .modal { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 1050; display: none; overflow: hidden; -webkit-overflow-scrolling: touch; outline: 0; } .modal.fade .modal-dialog { -webkit-transform: translate(0, -25%); -ms-transform: translate(0, -25%); -o-transform: translate(0, -25%); transform: translate(0, -25%); -webkit-transition: -webkit-transform 0.3s ease-out; -o-transition: -o-transform 0.3s ease-out; transition: -webkit-transform 0.3s ease-out; transition: transform 0.3s ease-out; transition: transform 0.3s ease-out, -webkit-transform 0.3s ease-out, -o-transform 0.3s ease-out; } .modal.in .modal-dialog { -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); -o-transform: translate(0, 0); transform: translate(0, 0); } .modal-open .modal { overflow-x: hidden; overflow-y: auto; } .modal-dialog { position: relative; width: auto; margin: 10px; } .modal-content { position: relative; background-color: #fff; background-clip: padding-box; border: 1px solid #999; border: 1px solid rgba(0, 0, 0, 0.2); border-radius: 6px; -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); outline: 0; } .modal-backdrop { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 1040; background-color: #000; } .modal-backdrop.fade { filter: alpha(opacity=0); opacity: 0; } .modal-backdrop.in { filter: alpha(opacity=50); opacity: 0.5; } .modal-header { padding: 15px; border-bottom: 1px solid #e5e5e5; } .modal-header .close { margin-top: -2px; } .modal-title { margin: 0; line-height: 1.42857143; } .modal-body { position: relative; padding: 15px; } .modal-footer { padding: 15px; text-align: right; border-top: 1px solid #e5e5e5; } .modal-footer .btn + .btn { margin-bottom: 0; margin-left: 5px; } .modal-footer .btn-group .btn + .btn { margin-left: -1px; } .modal-footer .btn-block + .btn-block { margin-left: 0; } .modal-scrollbar-measure { position: absolute; top: -9999px; width: 50px; height: 50px; overflow: scroll; } @media (min-width: 768px) { .modal-dialog { width: 600px; margin: 30px auto; } .modal-content { -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); } .modal-sm { width: 300px; } } @media (min-width: 992px) { .modal-lg { width: 900px; } } .tooltip { position: absolute; z-index: 1070; display: block; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-style: normal; font-weight: 400; line-height: 1.42857143; line-break: auto; text-align: left; text-align: start; text-decoration: none; text-shadow: none; text-transform: none; letter-spacing: normal; word-break: normal; word-spacing: normal; word-wrap: normal; white-space: normal; font-size: 12px; filter: alpha(opacity=0); opacity: 0; } .tooltip.in { filter: alpha(opacity=90); opacity: 0.9; } .tooltip.top { padding: 5px 0; margin-top: -3px; } .tooltip.right { padding: 0 5px; margin-left: 3px; } .tooltip.bottom { padding: 5px 0; margin-top: 3px; } .tooltip.left { padding: 0 5px; margin-left: -3px; } .tooltip.top .tooltip-arrow { bottom: 0; left: 50%; margin-left: -5px; border-width: 5px 5px 0; border-top-color: #000; } .tooltip.top-left .tooltip-arrow { right: 5px; bottom: 0; margin-bottom: -5px; border-width: 5px 5px 0; border-top-color: #000; } .tooltip.top-right .tooltip-arrow { bottom: 0; left: 5px; margin-bottom: -5px; border-width: 5px 5px 0; border-top-color: #000; } .tooltip.right .tooltip-arrow { top: 50%; left: 0; margin-top: -5px; border-width: 5px 5px 5px 0; border-right-color: #000; } .tooltip.left .tooltip-arrow { top: 50%; right: 0; margin-top: -5px; border-width: 5px 0 5px 5px; border-left-color: #000; } .tooltip.bottom .tooltip-arrow { top: 0; left: 50%; margin-left: -5px; border-width: 0 5px 5px; border-bottom-color: #000; } .tooltip.bottom-left .tooltip-arrow { top: 0; right: 5px; margin-top: -5px; border-width: 0 5px 5px; border-bottom-color: #000; } .tooltip.bottom-right .tooltip-arrow { top: 0; left: 5px; margin-top: -5px; border-width: 0 5px 5px; border-bottom-color: #000; } .tooltip-inner { max-width: 200px; padding: 3px 8px; color: #fff; text-align: center; background-color: #000; border-radius: 4px; } .tooltip-arrow { position: absolute; width: 0; height: 0; border-color: transparent; border-style: solid; } .popover { position: absolute; top: 0; left: 0; z-index: 1060; display: none; max-width: 276px; padding: 1px; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-style: normal; font-weight: 400; line-height: 1.42857143; line-break: auto; text-align: left; text-align: start; text-decoration: none; text-shadow: none; text-transform: none; letter-spacing: normal; word-break: normal; word-spacing: normal; word-wrap: normal; white-space: normal; font-size: 14px; background-color: #fff; background-clip: padding-box; border: 1px solid #ccc; border: 1px solid rgba(0, 0, 0, 0.2); border-radius: 6px; -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); } .popover.top { margin-top: -10px; } .popover.right { margin-left: 10px; } .popover.bottom { margin-top: 10px; } .popover.left { margin-left: -10px; } .popover > .arrow { border-width: 11px; } .popover > .arrow, .popover > .arrow:after { position: absolute; display: block; width: 0; height: 0; border-color: transparent; border-style: solid; } .popover > .arrow:after { content: ""; border-width: 10px; } .popover.top > .arrow { bottom: -11px; left: 50%; margin-left: -11px; border-top-color: #999999; border-top-color: rgba(0, 0, 0, 0.25); border-bottom-width: 0; } .popover.top > .arrow:after { bottom: 1px; margin-left: -10px; content: " "; border-top-color: #fff; border-bottom-width: 0; } .popover.right > .arrow { top: 50%; left: -11px; margin-top: -11px; border-right-color: #999999; border-right-color: rgba(0, 0, 0, 0.25); border-left-width: 0; } .popover.right > .arrow:after { bottom: -10px; left: 1px; content: " "; border-right-color: #fff; border-left-width: 0; } .popover.bottom > .arrow { top: -11px; left: 50%; margin-left: -11px; border-top-width: 0; border-bottom-color: #999999; border-bottom-color: rgba(0, 0, 0, 0.25); } .popover.bottom > .arrow:after { top: 1px; margin-left: -10px; content: " "; border-top-width: 0; border-bottom-color: #fff; } .popover.left > .arrow { top: 50%; right: -11px; margin-top: -11px; border-right-width: 0; border-left-color: #999999; border-left-color: rgba(0, 0, 0, 0.25); } .popover.left > .arrow:after { right: 1px; bottom: -10px; content: " "; border-right-width: 0; border-left-color: #fff; } .popover-title { padding: 8px 14px; margin: 0; font-size: 14px; background-color: #f7f7f7; border-bottom: 1px solid #ebebeb; border-radius: 5px 5px 0 0; } .popover-content { padding: 9px 14px; } .carousel { position: relative; } .carousel-inner { position: relative; width: 100%; overflow: hidden; } .carousel-inner > .item { position: relative; display: none; -webkit-transition: 0.6s ease-in-out left; -o-transition: 0.6s ease-in-out left; transition: 0.6s ease-in-out left; } .carousel-inner > .item > img, .carousel-inner > .item > a > img { line-height: 1; } @media all and (transform-3d), (-webkit-transform-3d) { .carousel-inner > .item { -webkit-transition: -webkit-transform 0.6s ease-in-out; -o-transition: -o-transform 0.6s ease-in-out; transition: -webkit-transform 0.6s ease-in-out; transition: transform 0.6s ease-in-out; transition: transform 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out, -o-transform 0.6s ease-in-out; -webkit-backface-visibility: hidden; backface-visibility: hidden; -webkit-perspective: 1000px; perspective: 1000px; } .carousel-inner > .item.next, .carousel-inner > .item.active.right { -webkit-transform: translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0); left: 0; } .carousel-inner > .item.prev, .carousel-inner > .item.active.left { -webkit-transform: translate3d(-100%, 0, 0); transform: translate3d(-100%, 0, 0); left: 0; } .carousel-inner > .item.next.left, .carousel-inner > .item.prev.right, .carousel-inner > .item.active { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); left: 0; } } .carousel-inner > .active, .carousel-inner > .next, .carousel-inner > .prev { display: block; } .carousel-inner > .active { left: 0; } .carousel-inner > .next, .carousel-inner > .prev { position: absolute; top: 0; width: 100%; } .carousel-inner > .next { left: 100%; } .carousel-inner > .prev { left: -100%; } .carousel-inner > .next.left, .carousel-inner > .prev.right { left: 0; } .carousel-inner > .active.left { left: -100%; } .carousel-inner > .active.right { left: 100%; } .carousel-control { position: absolute; top: 0; bottom: 0; left: 0; width: 15%; font-size: 20px; color: #fff; text-align: center; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); background-color: rgba(0, 0, 0, 0); filter: alpha(opacity=50); opacity: 0.5; } .carousel-control.left { background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.0001))); background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); background-repeat: repeat-x; } .carousel-control.right { right: 0; left: auto; background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.0001)), to(rgba(0, 0, 0, 0.5))); background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); background-repeat: repeat-x; } .carousel-control:hover, .carousel-control:focus { color: #fff; text-decoration: none; outline: 0; filter: alpha(opacity=90); opacity: 0.9; } .carousel-control .icon-prev, .carousel-control .icon-next, .carousel-control .glyphicon-chevron-left, .carousel-control .glyphicon-chevron-right { position: absolute; top: 50%; z-index: 5; display: inline-block; margin-top: -10px; } .carousel-control .icon-prev, .carousel-control .glyphicon-chevron-left { left: 50%; margin-left: -10px; } .carousel-control .icon-next, .carousel-control .glyphicon-chevron-right { right: 50%; margin-right: -10px; } .carousel-control .icon-prev, .carousel-control .icon-next { width: 20px; height: 20px; font-family: serif; line-height: 1; } .carousel-control .icon-prev:before { content: "\2039"; } .carousel-control .icon-next:before { content: "\203a"; } .carousel-indicators { position: absolute; bottom: 10px; left: 50%; z-index: 15; width: 60%; padding-left: 0; margin-left: -30%; text-align: center; list-style: none; } .carousel-indicators li { display: inline-block; width: 10px; height: 10px; margin: 1px; text-indent: -999px; cursor: pointer; background-color: #000 \9; background-color: rgba(0, 0, 0, 0); border: 1px solid #fff; border-radius: 10px; } .carousel-indicators .active { width: 12px; height: 12px; margin: 0; background-color: #fff; } .carousel-caption { position: absolute; right: 15%; bottom: 20px; left: 15%; z-index: 10; padding-top: 20px; padding-bottom: 20px; color: #fff; text-align: center; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); } .carousel-caption .btn { text-shadow: none; } @media screen and (min-width: 768px) { .carousel-control .glyphicon-chevron-left, .carousel-control .glyphicon-chevron-right, .carousel-control .icon-prev, .carousel-control .icon-next { width: 30px; height: 30px; margin-top: -10px; font-size: 30px; } .carousel-control .glyphicon-chevron-left, .carousel-control .icon-prev { margin-left: -10px; } .carousel-control .glyphicon-chevron-right, .carousel-control .icon-next { margin-right: -10px; } .carousel-caption { right: 20%; left: 20%; padding-bottom: 30px; } .carousel-indicators { bottom: 20px; } } .clearfix:before, .clearfix:after, .dl-horizontal dd:before, .dl-horizontal dd:after, .container:before, .container:after, .container-fluid:before, .container-fluid:after, .row:before, .row:after, .form-horizontal .form-group:before, .form-horizontal .form-group:after, .btn-toolbar:before, .btn-toolbar:after, .btn-group-vertical > .btn-group:before, .btn-group-vertical > .btn-group:after, .nav:before, .nav:after, .navbar:before, .navbar:after, .navbar-header:before, .navbar-header:after, .navbar-collapse:before, .navbar-collapse:after, .pager:before, .pager:after, .panel-body:before, .panel-body:after, .modal-header:before, .modal-header:after, .modal-footer:before, .modal-footer:after { display: table; content: " "; } .clearfix:after, .dl-horizontal dd:after, .container:after, .container-fluid:after, .row:after, .form-horizontal .form-group:after, .btn-toolbar:after, .btn-group-vertical > .btn-group:after, .nav:after, .navbar:after, .navbar-header:after, .navbar-collapse:after, .pager:after, .panel-body:after, .modal-header:after, .modal-footer:after { clear: both; } .center-block { display: block; margin-right: auto; margin-left: auto; } .pull-right { float: right !important; } .pull-left { float: left !important; } .hide { display: none !important; } .show { display: block !important; } .invisible { visibility: hidden; } .text-hide { font: 0/0 a; color: transparent; text-shadow: none; background-color: transparent; border: 0; } .hidden { display: none !important; } .affix { position: fixed; } @-ms-viewport { width: device-width; } .visible-xs, .visible-sm, .visible-md, .visible-lg { display: none !important; } .visible-xs-block, .visible-xs-inline, .visible-xs-inline-block, .visible-sm-block, .visible-sm-inline, .visible-sm-inline-block, .visible-md-block, .visible-md-inline, .visible-md-inline-block, .visible-lg-block, .visible-lg-inline, .visible-lg-inline-block { display: none !important; } @media (max-width: 767px) { .visible-xs { display: block !important; } table.visible-xs { display: table !important; } tr.visible-xs { display: table-row !important; } th.visible-xs, td.visible-xs { display: table-cell !important; } } @media (max-width: 767px) { .visible-xs-block { display: block !important; } } @media (max-width: 767px) { .visible-xs-inline { display: inline !important; } } @media (max-width: 767px) { .visible-xs-inline-block { display: inline-block !important; } } @media (min-width: 768px) and (max-width: 991px) { .visible-sm { display: block !important; } table.visible-sm { display: table !important; } tr.visible-sm { display: table-row !important; } th.visible-sm, td.visible-sm { display: table-cell !important; } } @media (min-width: 768px) and (max-width: 991px) { .visible-sm-block { display: block !important; } } @media (min-width: 768px) and (max-width: 991px) { .visible-sm-inline { display: inline !important; } } @media (min-width: 768px) and (max-width: 991px) { .visible-sm-inline-block { display: inline-block !important; } } @media (min-width: 992px) and (max-width: 1199px) { .visible-md { display: block !important; } table.visible-md { display: table !important; } tr.visible-md { display: table-row !important; } th.visible-md, td.visible-md { display: table-cell !important; } } @media (min-width: 992px) and (max-width: 1199px) { .visible-md-block { display: block !important; } } @media (min-width: 992px) and (max-width: 1199px) { .visible-md-inline { display: inline !important; } } @media (min-width: 992px) and (max-width: 1199px) { .visible-md-inline-block { display: inline-block !important; } } @media (min-width: 1200px) { .visible-lg { display: block !important; } table.visible-lg { display: table !important; } tr.visible-lg { display: table-row !important; } th.visible-lg, td.visible-lg { display: table-cell !important; } } @media (min-width: 1200px) { .visible-lg-block { display: block !important; } } @media (min-width: 1200px) { .visible-lg-inline { display: inline !important; } } @media (min-width: 1200px) { .visible-lg-inline-block { display: inline-block !important; } } @media (max-width: 767px) { .hidden-xs { display: none !important; } } @media (min-width: 768px) and (max-width: 991px) { .hidden-sm { display: none !important; } } @media (min-width: 992px) and (max-width: 1199px) { .hidden-md { display: none !important; } } @media (min-width: 1200px) { .hidden-lg { display: none !important; } } .visible-print { display: none !important; } @media print { .visible-print { display: block !important; } table.visible-print { display: table !important; } tr.visible-print { display: table-row !important; } th.visible-print, td.visible-print { display: table-cell !important; } } .visible-print-block { display: none !important; } @media print { .visible-print-block { display: block !important; } } .visible-print-inline { display: none !important; } @media print { .visible-print-inline { display: inline !important; } } .visible-print-inline-block { display: none !important; } @media print { .visible-print-inline-block { display: inline-block !important; } } @media print { .hidden-print { display: none !important; } } /*# sourceMappingURL=bootstrap.css.map */ ================================================ FILE: doc/_build/css/site.css ================================================ .urubu { background-image: url("../img/urubu_cover.png"); background-size: cover; color: white; } body { position: relative; padding-top: 50px; padding-bottom: 20px; } .page-header { margin-top: 30px; } .breadcrumb { margin-top: 20px; } .content h2:first-of-type { margin-top: 0px; } .half-rule { width: 100px; margin: 25px auto; } .fa { margin-right: 0.5em; } .checklist { padding: 0; list-style: none; } /* footer */ .footer { margin-top: 30px; padding-top: 16px; color: #777; border-top: 1px solid #eee; font-size: 90%; text-align: center; } .footer p { margin: 0px; } /* toc */ .sidebar { font-size: 90%; line-height: normal } .toc ul { padding-left: 0; list-style: none; } .toc ul li { padding-top: 3px; } .toc ul ul { padding-left: 10px; font-size: 95%; } /* heading scrolling */ h2[id]:before, h3[id]:before{ content: ""; display: block; height: 70px; margin-top:-70px; } /* affix hacks from boostrap 3.0 docs */ .sidebar.affix { position: static; } @media (min-width: 992px) { /* Widen the fixed sidebar */ .sidebar.affix, .sidebar.affix-bottom { width: 213px; } .sidebar.affix { position: fixed; /* Undo the static from mobile first approach */ top: 80px; } .sidebar.affix-bottom { position: absolute; /* Undo the static from mobile first approach */ } } @media (min-width: 1200px) { /* Widen the fixed sidebar again */ .sidebar.affix, .sidebar.affix-bottom { width: 263px; } } ================================================ FILE: doc/_build/css/syntax.css ================================================ .codehilite { background: #ffffff; } .codehilite .c { color: #999988; font-style: italic } /* Comment */ .codehilite .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .codehilite .k { font-weight: bold } /* Keyword */ .codehilite .o { font-weight: bold } /* Operator */ .codehilite .cm { color: #999988; font-style: italic } /* Comment.Multiline */ .codehilite .cp { color: #999999; font-weight: bold } /* Comment.Preproc */ .codehilite .c1 { color: #999988; font-style: italic } /* Comment.Single */ .codehilite .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */ .codehilite .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .codehilite .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */ .codehilite .ge { font-style: italic } /* Generic.Emph */ .codehilite .gr { color: #aa0000 } /* Generic.Error */ .codehilite .gh { color: #999999 } /* Generic.Heading */ .codehilite .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .codehilite .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */ .codehilite .go { color: #888888 } /* Generic.Output */ .codehilite .gp { color: #555555 } /* Generic.Prompt */ .codehilite .gs { font-weight: bold } /* Generic.Strong */ .codehilite .gu { color: #aaaaaa } /* Generic.Subheading */ .codehilite .gt { color: #aa0000 } /* Generic.Traceback */ .codehilite .kc { font-weight: bold } /* Keyword.Constant */ .codehilite .kd { font-weight: bold } /* Keyword.Declaration */ .codehilite .kp { font-weight: bold } /* Keyword.Pseudo */ .codehilite .kr { font-weight: bold } /* Keyword.Reserved */ .codehilite .kt { color: #445588; font-weight: bold } /* Keyword.Type */ .codehilite .m { color: #009999 } /* Literal.Number */ .codehilite .s { color: #d14 } /* Literal.String */ .codehilite .na { color: #008080 } /* Name.Attribute */ .codehilite .nb { color: #0086B3 } /* Name.Builtin */ .codehilite .nc { color: #445588; font-weight: bold } /* Name.Class */ .codehilite .no { color: #008080 } /* Name.Constant */ .codehilite .ni { color: #800080 } /* Name.Entity */ .codehilite .ne { color: #990000; font-weight: bold } /* Name.Exception */ .codehilite .nf { color: #990000; font-weight: bold } /* Name.Function */ .codehilite .nn { color: #555555 } /* Name.Namespace */ .codehilite .nt { color: #000080 } /* Name.Tag */ .codehilite .nv { color: #008080 } /* Name.Variable */ .codehilite .ow { font-weight: bold } /* Operator.Word */ .codehilite .w { color: #bbbbbb } /* Text.Whitespace */ .codehilite .mf { color: #009999 } /* Literal.Number.Float */ .codehilite .mh { color: #009999 } /* Literal.Number.Hex */ .codehilite .mi { color: #009999 } /* Literal.Number.Integer */ .codehilite .mo { color: #009999 } /* Literal.Number.Oct */ .codehilite .sb { color: #d14 } /* Literal.String.Backtick */ .codehilite .sc { color: #d14 } /* Literal.String.Char */ .codehilite .sd { color: #d14 } /* Literal.String.Doc */ .codehilite .s2 { color: #d14 } /* Literal.String.Double */ .codehilite .se { color: #d14 } /* Literal.String.Escape */ .codehilite .sh { color: #d14 } /* Literal.String.Heredoc */ .codehilite .si { color: #d14 } /* Literal.String.Interpol */ .codehilite .sx { color: #d14 } /* Literal.String.Other */ .codehilite .sr { color: #009926 } /* Literal.String.Regex */ .codehilite .s1 { color: #d14 } /* Literal.String.Single */ .codehilite .ss { color: #990073 } /* Literal.String.Symbol */ .codehilite .bp { color: #999999 } /* Name.Builtin.Pseudo */ .codehilite .vc { color: #008080 } /* Name.Variable.Class */ .codehilite .vg { color: #008080 } /* Name.Variable.Global */ .codehilite .vi { color: #008080 } /* Name.Variable.Instance */ .codehilite .il { color: #009999 } /* Literal.Number.Integer.Long */ ================================================ FILE: doc/_build/faq/baseurl-preview.html ================================================ How to preview sites that use the baseurl option?

Urubu version 0.8 and higher

The urubu serve command takes the baseurl setting automatically into account.

Urubu version 0.7

The urubu serve server does not include the baseurl prefix when serving pages so sites that use baseurl can't be previewed locally using urubu serve. An alternative option is to use tservice, which includes an option to serve a local static site with a URL prefix. To use tservice with an Urubu site instead of using urubu serve call tserve with the prefix option, e.g.

tserve --prefix <baseurl> _build

Where <baseurl> is your site's particular prefix.

================================================ FILE: doc/_build/faq/formulas.html ================================================ Is there a way to render formulas?

Yes: you can easily use MathJax with Urubu. Read more about it here.

================================================ FILE: doc/_build/faq/index.html ================================================ FAQ

FAQ

================================================ FILE: doc/_build/faq/licensing-requirements.html ================================================ What are the licensing requirements?

Urubu is licensed under the GNU Affero General Public License.

The first thing to understand is that this license applies only to the Urubu software. It has no implications on website projects managed with Urubu. You are free to license your projects in any way you choose.

The license only becomes relevant when you release a modified version of the Urubu software to the public in some way. In that case, you have to release the modified source code also, under the same license.

With the original GPL, a release meant shipping software to user that would install and run it locally. However, these days software is often made available by running it on a server. Under the original GPL, there would be no requirement to release the modified source code in such as case. This clearly violates the spirit of the GNU Licenses.

The GNU Affero General Public License fixes that problem. If you make the modified software available by running it on a server, you have to make the modified source code available to the users under the same license.

================================================ FILE: doc/_build/faq/link2section.html ================================================ Can I specify a link to a section in a page?

Yes, Urubu support links to page sections. Read this blog post to learn how.

================================================ FILE: doc/_build/faq/media-files.html ================================================ How to add media files?

The source structure of a project is preserved in the built website, and all non-markdown content files are copied verbatim. See Project structure.

Therefore, you can put media files at any convenient place in the source, and refer to them using Markdown image syntax, with a relative or root-relative path to the source file.

================================================ FILE: doc/_build/faq/sitemap.html ================================================ How do I make a sitemap?

To generate a sitemap you need to do the following:

  • Create a markdown file called sitemap.md like this:
---
title: sitemap
layout: sitemap
changefreq: monthly
priority: 1.0
xmlns: http://www.google.com/schemas/sitemap/0.84
saveas: sitemap.xml
---
  • Provide a sitemap.html in the _layouts directory, with looking something like the following:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="{{ this.xmlns }}">
{% for t in site.reflinks %}
    {% if site.reflinks[t].fn and not site.reflinks[t].hidden %}
    <url>
        <loc>{{ site.hostname }}{{ site.reflinks[t].url }}</loc>
        <changefreq>{{ this.changefreq }}</changefreq>
        <priority>{{ this.priority }}</priority>
    </url>
    {% endif %}
{% endfor %}
</urlset>

What makes this work is for the main part the saveas parameter in the sitemap.md file, which overrides the default output filename with sitemap.xml instead of sitemap.html. If you add other sitemaps don't forget to specify distinct id and saveas for each one, to prevent Ambiguous reference id errors.

================================================ FILE: doc/_build/faq/tags.html ================================================ How to use tags?

Urubu supports tags. To use them, you need 2 things:

  • Assign the desired tags to content pages, by assigning a tag or a list of tags to the tags attribute. See also: Content files.

  • Provide a tag.html layout in the _layouts directory.

It is the existence of the tag.html layout that triggers the generation of tag-related content. For example, if you have used tags bar and foo in the project, you will see that the _build folder contains tag/bar/index.html and tag/foo/index.html. Those index files use the tag.html layout to show the content related to a tag.

Presumably, there is already a general index.html layout to show content in a folder. An initial tag.html layout can then be a one-liner by using template inheritance, like so:

{% extends "index.html" %}

Of course, you may want to specialize the tag.html layout further to better reflect the purpose.

Urubu also generates the corresponding tag objects so that you can use them in your layouts. This is described in Tag objects.

Note that the _build will contain a top-level tag folder, even when the source directory does not. Optionally, you can define the tag folder in the source also. You can then define an index file and set attributes such as the layout to display the tags themselves. However, the content will be generated by Urubu automatically and needs not be set. See also: Tag folder object.

================================================ FILE: doc/_build/index.html ================================================ Urubu

Urubu

A micro CMS for static websites

30-Mar-2026: Urubu 1.4.1 released

For websites, not just blogs

Set up a website as logically related content. Content ordering is flexible, not just by date.

Focus on navigation

Easily set up a navbar, a table of contents sidebar, breadcrumbs and pagers.

Ready for Bootstrap

Urubu plays well with Bootstrap, the popular framework for great looking websites.

Markdown content

Enter content in light-weight Markdown syntax, with popular extensions.

Wiki links

Easily refer to other pages like in wikis, using Markdown syntax.

Powerful templating

Use the powerful Jinja2 templating library to define page layouts.

Sophisticated control

Per-page control of page layout and other stuff. Plus user-defined variables.

Python power

Urubu is built with Python. It provides Python hooks to assist in templating.

Ideal with git

Use a git workflow to develop your website. Deploy by pushing.


And of course, it's open source!

================================================ FILE: doc/_build/js/bootstrap.js ================================================ /*! * Bootstrap v3.4.1 (https://getbootstrap.com/) * Copyright 2011-2019 Twitter, Inc. * Licensed under the MIT license */ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript requires jQuery') } +function ($) { 'use strict'; var version = $.fn.jquery.split(' ')[0].split('.') if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) { throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4') } }(jQuery); /* ======================================================================== * Bootstrap: transition.js v3.4.1 * https://getbootstrap.com/docs/3.4/javascript/#transitions * ======================================================================== * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // CSS TRANSITION SUPPORT (Shoutout: https://modernizr.com/) // ============================================================ function transitionEnd() { var el = document.createElement('bootstrap') var transEndEventNames = { WebkitTransition : 'webkitTransitionEnd', MozTransition : 'transitionend', OTransition : 'oTransitionEnd otransitionend', transition : 'transitionend' } for (var name in transEndEventNames) { if (el.style[name] !== undefined) { return { end: transEndEventNames[name] } } } return false // explicit for ie8 ( ._.) } // https://blog.alexmaccaw.com/css-transitions $.fn.emulateTransitionEnd = function (duration) { var called = false var $el = this $(this).one('bsTransitionEnd', function () { called = true }) var callback = function () { if (!called) $($el).trigger($.support.transition.end) } setTimeout(callback, duration) return this } $(function () { $.support.transition = transitionEnd() if (!$.support.transition) return $.event.special.bsTransitionEnd = { bindType: $.support.transition.end, delegateType: $.support.transition.end, handle: function (e) { if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments) } } }) }(jQuery); /* ======================================================================== * Bootstrap: alert.js v3.4.1 * https://getbootstrap.com/docs/3.4/javascript/#alerts * ======================================================================== * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // ALERT CLASS DEFINITION // ====================== var dismiss = '[data-dismiss="alert"]' var Alert = function (el) { $(el).on('click', dismiss, this.close) } Alert.VERSION = '3.4.1' Alert.TRANSITION_DURATION = 150 Alert.prototype.close = function (e) { var $this = $(this) var selector = $this.attr('data-target') if (!selector) { selector = $this.attr('href') selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 } selector = selector === '#' ? [] : selector var $parent = $(document).find(selector) if (e) e.preventDefault() if (!$parent.length) { $parent = $this.closest('.alert') } $parent.trigger(e = $.Event('close.bs.alert')) if (e.isDefaultPrevented()) return $parent.removeClass('in') function removeElement() { // detach from parent, fire event then clean up data $parent.detach().trigger('closed.bs.alert').remove() } $.support.transition && $parent.hasClass('fade') ? $parent .one('bsTransitionEnd', removeElement) .emulateTransitionEnd(Alert.TRANSITION_DURATION) : removeElement() } // ALERT PLUGIN DEFINITION // ======================= function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.alert') if (!data) $this.data('bs.alert', (data = new Alert(this))) if (typeof option == 'string') data[option].call($this) }) } var old = $.fn.alert $.fn.alert = Plugin $.fn.alert.Constructor = Alert // ALERT NO CONFLICT // ================= $.fn.alert.noConflict = function () { $.fn.alert = old return this } // ALERT DATA-API // ============== $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) }(jQuery); /* ======================================================================== * Bootstrap: button.js v3.4.1 * https://getbootstrap.com/docs/3.4/javascript/#buttons * ======================================================================== * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // BUTTON PUBLIC CLASS DEFINITION // ============================== var Button = function (element, options) { this.$element = $(element) this.options = $.extend({}, Button.DEFAULTS, options) this.isLoading = false } Button.VERSION = '3.4.1' Button.DEFAULTS = { loadingText: 'loading...' } Button.prototype.setState = function (state) { var d = 'disabled' var $el = this.$element var val = $el.is('input') ? 'val' : 'html' var data = $el.data() state += 'Text' if (data.resetText == null) $el.data('resetText', $el[val]()) // push to event loop to allow forms to submit setTimeout($.proxy(function () { $el[val](data[state] == null ? this.options[state] : data[state]) if (state == 'loadingText') { this.isLoading = true $el.addClass(d).attr(d, d).prop(d, true) } else if (this.isLoading) { this.isLoading = false $el.removeClass(d).removeAttr(d).prop(d, false) } }, this), 0) } Button.prototype.toggle = function () { var changed = true var $parent = this.$element.closest('[data-toggle="buttons"]') if ($parent.length) { var $input = this.$element.find('input') if ($input.prop('type') == 'radio') { if ($input.prop('checked')) changed = false $parent.find('.active').removeClass('active') this.$element.addClass('active') } else if ($input.prop('type') == 'checkbox') { if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false this.$element.toggleClass('active') } $input.prop('checked', this.$element.hasClass('active')) if (changed) $input.trigger('change') } else { this.$element.attr('aria-pressed', !this.$element.hasClass('active')) this.$element.toggleClass('active') } } // BUTTON PLUGIN DEFINITION // ======================== function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.button') var options = typeof option == 'object' && option if (!data) $this.data('bs.button', (data = new Button(this, options))) if (option == 'toggle') data.toggle() else if (option) data.setState(option) }) } var old = $.fn.button $.fn.button = Plugin $.fn.button.Constructor = Button // BUTTON NO CONFLICT // ================== $.fn.button.noConflict = function () { $.fn.button = old return this } // BUTTON DATA-API // =============== $(document) .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) { var $btn = $(e.target).closest('.btn') Plugin.call($btn, 'toggle') if (!($(e.target).is('input[type="radio"], input[type="checkbox"]'))) { // Prevent double click on radios, and the double selections (so cancellation) on checkboxes e.preventDefault() // The target component still receive the focus if ($btn.is('input,button')) $btn.trigger('focus') else $btn.find('input:visible,button:visible').first().trigger('focus') } }) .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) { $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type)) }) }(jQuery); /* ======================================================================== * Bootstrap: carousel.js v3.4.1 * https://getbootstrap.com/docs/3.4/javascript/#carousel * ======================================================================== * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // CAROUSEL CLASS DEFINITION // ========================= var Carousel = function (element, options) { this.$element = $(element) this.$indicators = this.$element.find('.carousel-indicators') this.options = options this.paused = null this.sliding = null this.interval = null this.$active = null this.$items = null this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this)) this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element .on('mouseenter.bs.carousel', $.proxy(this.pause, this)) .on('mouseleave.bs.carousel', $.proxy(this.cycle, this)) } Carousel.VERSION = '3.4.1' Carousel.TRANSITION_DURATION = 600 Carousel.DEFAULTS = { interval: 5000, pause: 'hover', wrap: true, keyboard: true } Carousel.prototype.keydown = function (e) { if (/input|textarea/i.test(e.target.tagName)) return switch (e.which) { case 37: this.prev(); break case 39: this.next(); break default: return } e.preventDefault() } Carousel.prototype.cycle = function (e) { e || (this.paused = false) this.interval && clearInterval(this.interval) this.options.interval && !this.paused && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) return this } Carousel.prototype.getItemIndex = function (item) { this.$items = item.parent().children('.item') return this.$items.index(item || this.$active) } Carousel.prototype.getItemForDirection = function (direction, active) { var activeIndex = this.getItemIndex(active) var willWrap = (direction == 'prev' && activeIndex === 0) || (direction == 'next' && activeIndex == (this.$items.length - 1)) if (willWrap && !this.options.wrap) return active var delta = direction == 'prev' ? -1 : 1 var itemIndex = (activeIndex + delta) % this.$items.length return this.$items.eq(itemIndex) } Carousel.prototype.to = function (pos) { var that = this var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active')) if (pos > (this.$items.length - 1) || pos < 0) return if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid" if (activeIndex == pos) return this.pause().cycle() return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos)) } Carousel.prototype.pause = function (e) { e || (this.paused = true) if (this.$element.find('.next, .prev').length && $.support.transition) { this.$element.trigger($.support.transition.end) this.cycle(true) } this.interval = clearInterval(this.interval) return this } Carousel.prototype.next = function () { if (this.sliding) return return this.slide('next') } Carousel.prototype.prev = function () { if (this.sliding) return return this.slide('prev') } Carousel.prototype.slide = function (type, next) { var $active = this.$element.find('.item.active') var $next = next || this.getItemForDirection(type, $active) var isCycling = this.interval var direction = type == 'next' ? 'left' : 'right' var that = this if ($next.hasClass('active')) return (this.sliding = false) var relatedTarget = $next[0] var slideEvent = $.Event('slide.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) this.$element.trigger(slideEvent) if (slideEvent.isDefaultPrevented()) return this.sliding = true isCycling && this.pause() if (this.$indicators.length) { this.$indicators.find('.active').removeClass('active') var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)]) $nextIndicator && $nextIndicator.addClass('active') } var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid" if ($.support.transition && this.$element.hasClass('slide')) { $next.addClass(type) if (typeof $next === 'object' && $next.length) { $next[0].offsetWidth // force reflow } $active.addClass(direction) $next.addClass(direction) $active .one('bsTransitionEnd', function () { $next.removeClass([type, direction].join(' ')).addClass('active') $active.removeClass(['active', direction].join(' ')) that.sliding = false setTimeout(function () { that.$element.trigger(slidEvent) }, 0) }) .emulateTransitionEnd(Carousel.TRANSITION_DURATION) } else { $active.removeClass('active') $next.addClass('active') this.sliding = false this.$element.trigger(slidEvent) } isCycling && this.cycle() return this } // CAROUSEL PLUGIN DEFINITION // ========================== function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.carousel') var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) var action = typeof option == 'string' ? option : options.slide if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) if (typeof option == 'number') data.to(option) else if (action) data[action]() else if (options.interval) data.pause().cycle() }) } var old = $.fn.carousel $.fn.carousel = Plugin $.fn.carousel.Constructor = Carousel // CAROUSEL NO CONFLICT // ==================== $.fn.carousel.noConflict = function () { $.fn.carousel = old return this } // CAROUSEL DATA-API // ================= var clickHandler = function (e) { var $this = $(this) var href = $this.attr('href') if (href) { href = href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 } var target = $this.attr('data-target') || href var $target = $(document).find(target) if (!$target.hasClass('carousel')) return var options = $.extend({}, $target.data(), $this.data()) var slideIndex = $this.attr('data-slide-to') if (slideIndex) options.interval = false Plugin.call($target, options) if (slideIndex) { $target.data('bs.carousel').to(slideIndex) } e.preventDefault() } $(document) .on('click.bs.carousel.data-api', '[data-slide]', clickHandler) .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler) $(window).on('load', function () { $('[data-ride="carousel"]').each(function () { var $carousel = $(this) Plugin.call($carousel, $carousel.data()) }) }) }(jQuery); /* ======================================================================== * Bootstrap: collapse.js v3.4.1 * https://getbootstrap.com/docs/3.4/javascript/#collapse * ======================================================================== * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ /* jshint latedef: false */ +function ($) { 'use strict'; // COLLAPSE PUBLIC CLASS DEFINITION // ================================ var Collapse = function (element, options) { this.$element = $(element) this.options = $.extend({}, Collapse.DEFAULTS, options) this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' + '[data-toggle="collapse"][data-target="#' + element.id + '"]') this.transitioning = null if (this.options.parent) { this.$parent = this.getParent() } else { this.addAriaAndCollapsedClass(this.$element, this.$trigger) } if (this.options.toggle) this.toggle() } Collapse.VERSION = '3.4.1' Collapse.TRANSITION_DURATION = 350 Collapse.DEFAULTS = { toggle: true } Collapse.prototype.dimension = function () { var hasWidth = this.$element.hasClass('width') return hasWidth ? 'width' : 'height' } Collapse.prototype.show = function () { if (this.transitioning || this.$element.hasClass('in')) return var activesData var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing') if (actives && actives.length) { activesData = actives.data('bs.collapse') if (activesData && activesData.transitioning) return } var startEvent = $.Event('show.bs.collapse') this.$element.trigger(startEvent) if (startEvent.isDefaultPrevented()) return if (actives && actives.length) { Plugin.call(actives, 'hide') activesData || actives.data('bs.collapse', null) } var dimension = this.dimension() this.$element .removeClass('collapse') .addClass('collapsing')[dimension](0) .attr('aria-expanded', true) this.$trigger .removeClass('collapsed') .attr('aria-expanded', true) this.transitioning = 1 var complete = function () { this.$element .removeClass('collapsing') .addClass('collapse in')[dimension]('') this.transitioning = 0 this.$element .trigger('shown.bs.collapse') } if (!$.support.transition) return complete.call(this) var scrollSize = $.camelCase(['scroll', dimension].join('-')) this.$element .one('bsTransitionEnd', $.proxy(complete, this)) .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize]) } Collapse.prototype.hide = function () { if (this.transitioning || !this.$element.hasClass('in')) return var startEvent = $.Event('hide.bs.collapse') this.$element.trigger(startEvent) if (startEvent.isDefaultPrevented()) return var dimension = this.dimension() this.$element[dimension](this.$element[dimension]())[0].offsetHeight this.$element .addClass('collapsing') .removeClass('collapse in') .attr('aria-expanded', false) this.$trigger .addClass('collapsed') .attr('aria-expanded', false) this.transitioning = 1 var complete = function () { this.transitioning = 0 this.$element .removeClass('collapsing') .addClass('collapse') .trigger('hidden.bs.collapse') } if (!$.support.transition) return complete.call(this) this.$element [dimension](0) .one('bsTransitionEnd', $.proxy(complete, this)) .emulateTransitionEnd(Collapse.TRANSITION_DURATION) } Collapse.prototype.toggle = function () { this[this.$element.hasClass('in') ? 'hide' : 'show']() } Collapse.prototype.getParent = function () { return $(document).find(this.options.parent) .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]') .each($.proxy(function (i, element) { var $element = $(element) this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element) }, this)) .end() } Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) { var isOpen = $element.hasClass('in') $element.attr('aria-expanded', isOpen) $trigger .toggleClass('collapsed', !isOpen) .attr('aria-expanded', isOpen) } function getTargetFromTrigger($trigger) { var href var target = $trigger.attr('data-target') || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 return $(document).find(target) } // COLLAPSE PLUGIN DEFINITION // ========================== function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.collapse') var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) if (typeof option == 'string') data[option]() }) } var old = $.fn.collapse $.fn.collapse = Plugin $.fn.collapse.Constructor = Collapse // COLLAPSE NO CONFLICT // ==================== $.fn.collapse.noConflict = function () { $.fn.collapse = old return this } // COLLAPSE DATA-API // ================= $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { var $this = $(this) if (!$this.attr('data-target')) e.preventDefault() var $target = getTargetFromTrigger($this) var data = $target.data('bs.collapse') var option = data ? 'toggle' : $this.data() Plugin.call($target, option) }) }(jQuery); /* ======================================================================== * Bootstrap: dropdown.js v3.4.1 * https://getbootstrap.com/docs/3.4/javascript/#dropdowns * ======================================================================== * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // DROPDOWN CLASS DEFINITION // ========================= var backdrop = '.dropdown-backdrop' var toggle = '[data-toggle="dropdown"]' var Dropdown = function (element) { $(element).on('click.bs.dropdown', this.toggle) } Dropdown.VERSION = '3.4.1' function getParent($this) { var selector = $this.attr('data-target') if (!selector) { selector = $this.attr('href') selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 } var $parent = selector !== '#' ? $(document).find(selector) : null return $parent && $parent.length ? $parent : $this.parent() } function clearMenus(e) { if (e && e.which === 3) return $(backdrop).remove() $(toggle).each(function () { var $this = $(this) var $parent = getParent($this) var relatedTarget = { relatedTarget: this } if (!$parent.hasClass('open')) return if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget)) if (e.isDefaultPrevented()) return $this.attr('aria-expanded', 'false') $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget)) }) } Dropdown.prototype.toggle = function (e) { var $this = $(this) if ($this.is('.disabled, :disabled')) return var $parent = getParent($this) var isActive = $parent.hasClass('open') clearMenus() if (!isActive) { if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { // if mobile we use a backdrop because click events don't delegate $(document.createElement('div')) .addClass('dropdown-backdrop') .insertAfter($(this)) .on('click', clearMenus) } var relatedTarget = { relatedTarget: this } $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget)) if (e.isDefaultPrevented()) return $this .trigger('focus') .attr('aria-expanded', 'true') $parent .toggleClass('open') .trigger($.Event('shown.bs.dropdown', relatedTarget)) } return false } Dropdown.prototype.keydown = function (e) { if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return var $this = $(this) e.preventDefault() e.stopPropagation() if ($this.is('.disabled, :disabled')) return var $parent = getParent($this) var isActive = $parent.hasClass('open') if (!isActive && e.which != 27 || isActive && e.which == 27) { if (e.which == 27) $parent.find(toggle).trigger('focus') return $this.trigger('click') } var desc = ' li:not(.disabled):visible a' var $items = $parent.find('.dropdown-menu' + desc) if (!$items.length) return var index = $items.index(e.target) if (e.which == 38 && index > 0) index-- // up if (e.which == 40 && index < $items.length - 1) index++ // down if (!~index) index = 0 $items.eq(index).trigger('focus') } // DROPDOWN PLUGIN DEFINITION // ========================== function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.dropdown') if (!data) $this.data('bs.dropdown', (data = new Dropdown(this))) if (typeof option == 'string') data[option].call($this) }) } var old = $.fn.dropdown $.fn.dropdown = Plugin $.fn.dropdown.Constructor = Dropdown // DROPDOWN NO CONFLICT // ==================== $.fn.dropdown.noConflict = function () { $.fn.dropdown = old return this } // APPLY TO STANDARD DROPDOWN ELEMENTS // =================================== $(document) .on('click.bs.dropdown.data-api', clearMenus) .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown) .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown) }(jQuery); /* ======================================================================== * Bootstrap: modal.js v3.4.1 * https://getbootstrap.com/docs/3.4/javascript/#modals * ======================================================================== * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // MODAL CLASS DEFINITION // ====================== var Modal = function (element, options) { this.options = options this.$body = $(document.body) this.$element = $(element) this.$dialog = this.$element.find('.modal-dialog') this.$backdrop = null this.isShown = null this.originalBodyPad = null this.scrollbarWidth = 0 this.ignoreBackdropClick = false this.fixedContent = '.navbar-fixed-top, .navbar-fixed-bottom' if (this.options.remote) { this.$element .find('.modal-content') .load(this.options.remote, $.proxy(function () { this.$element.trigger('loaded.bs.modal') }, this)) } } Modal.VERSION = '3.4.1' Modal.TRANSITION_DURATION = 300 Modal.BACKDROP_TRANSITION_DURATION = 150 Modal.DEFAULTS = { backdrop: true, keyboard: true, show: true } Modal.prototype.toggle = function (_relatedTarget) { return this.isShown ? this.hide() : this.show(_relatedTarget) } Modal.prototype.show = function (_relatedTarget) { var that = this var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget }) this.$element.trigger(e) if (this.isShown || e.isDefaultPrevented()) return this.isShown = true this.checkScrollbar() this.setScrollbar() this.$body.addClass('modal-open') this.escape() this.resize() this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this)) this.$dialog.on('mousedown.dismiss.bs.modal', function () { that.$element.one('mouseup.dismiss.bs.modal', function (e) { if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true }) }) this.backdrop(function () { var transition = $.support.transition && that.$element.hasClass('fade') if (!that.$element.parent().length) { that.$element.appendTo(that.$body) // don't move modals dom position } that.$element .show() .scrollTop(0) that.adjustDialog() if (transition) { that.$element[0].offsetWidth // force reflow } that.$element.addClass('in') that.enforceFocus() var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) transition ? that.$dialog // wait for modal to slide in .one('bsTransitionEnd', function () { that.$element.trigger('focus').trigger(e) }) .emulateTransitionEnd(Modal.TRANSITION_DURATION) : that.$element.trigger('focus').trigger(e) }) } Modal.prototype.hide = function (e) { if (e) e.preventDefault() e = $.Event('hide.bs.modal') this.$element.trigger(e) if (!this.isShown || e.isDefaultPrevented()) return this.isShown = false this.escape() this.resize() $(document).off('focusin.bs.modal') this.$element .removeClass('in') .off('click.dismiss.bs.modal') .off('mouseup.dismiss.bs.modal') this.$dialog.off('mousedown.dismiss.bs.modal') $.support.transition && this.$element.hasClass('fade') ? this.$element .one('bsTransitionEnd', $.proxy(this.hideModal, this)) .emulateTransitionEnd(Modal.TRANSITION_DURATION) : this.hideModal() } Modal.prototype.enforceFocus = function () { $(document) .off('focusin.bs.modal') // guard against infinite focus loop .on('focusin.bs.modal', $.proxy(function (e) { if (document !== e.target && this.$element[0] !== e.target && !this.$element.has(e.target).length) { this.$element.trigger('focus') } }, this)) } Modal.prototype.escape = function () { if (this.isShown && this.options.keyboard) { this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) { e.which == 27 && this.hide() }, this)) } else if (!this.isShown) { this.$element.off('keydown.dismiss.bs.modal') } } Modal.prototype.resize = function () { if (this.isShown) { $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this)) } else { $(window).off('resize.bs.modal') } } Modal.prototype.hideModal = function () { var that = this this.$element.hide() this.backdrop(function () { that.$body.removeClass('modal-open') that.resetAdjustments() that.resetScrollbar() that.$element.trigger('hidden.bs.modal') }) } Modal.prototype.removeBackdrop = function () { this.$backdrop && this.$backdrop.remove() this.$backdrop = null } Modal.prototype.backdrop = function (callback) { var that = this var animate = this.$element.hasClass('fade') ? 'fade' : '' if (this.isShown && this.options.backdrop) { var doAnimate = $.support.transition && animate this.$backdrop = $(document.createElement('div')) .addClass('modal-backdrop ' + animate) .appendTo(this.$body) this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) { if (this.ignoreBackdropClick) { this.ignoreBackdropClick = false return } if (e.target !== e.currentTarget) return this.options.backdrop == 'static' ? this.$element[0].focus() : this.hide() }, this)) if (doAnimate) this.$backdrop[0].offsetWidth // force reflow this.$backdrop.addClass('in') if (!callback) return doAnimate ? this.$backdrop .one('bsTransitionEnd', callback) .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : callback() } else if (!this.isShown && this.$backdrop) { this.$backdrop.removeClass('in') var callbackRemove = function () { that.removeBackdrop() callback && callback() } $.support.transition && this.$element.hasClass('fade') ? this.$backdrop .one('bsTransitionEnd', callbackRemove) .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : callbackRemove() } else if (callback) { callback() } } // these following methods are used to handle overflowing modals Modal.prototype.handleUpdate = function () { this.adjustDialog() } Modal.prototype.adjustDialog = function () { var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight this.$element.css({ paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '', paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : '' }) } Modal.prototype.resetAdjustments = function () { this.$element.css({ paddingLeft: '', paddingRight: '' }) } Modal.prototype.checkScrollbar = function () { var fullWindowWidth = window.innerWidth if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8 var documentElementRect = document.documentElement.getBoundingClientRect() fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left) } this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth this.scrollbarWidth = this.measureScrollbar() } Modal.prototype.setScrollbar = function () { var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10) this.originalBodyPad = document.body.style.paddingRight || '' var scrollbarWidth = this.scrollbarWidth if (this.bodyIsOverflowing) { this.$body.css('padding-right', bodyPad + scrollbarWidth) $(this.fixedContent).each(function (index, element) { var actualPadding = element.style.paddingRight var calculatedPadding = $(element).css('padding-right') $(element) .data('padding-right', actualPadding) .css('padding-right', parseFloat(calculatedPadding) + scrollbarWidth + 'px') }) } } Modal.prototype.resetScrollbar = function () { this.$body.css('padding-right', this.originalBodyPad) $(this.fixedContent).each(function (index, element) { var padding = $(element).data('padding-right') $(element).removeData('padding-right') element.style.paddingRight = padding ? padding : '' }) } Modal.prototype.measureScrollbar = function () { // thx walsh var scrollDiv = document.createElement('div') scrollDiv.className = 'modal-scrollbar-measure' this.$body.append(scrollDiv) var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth this.$body[0].removeChild(scrollDiv) return scrollbarWidth } // MODAL PLUGIN DEFINITION // ======================= function Plugin(option, _relatedTarget) { return this.each(function () { var $this = $(this) var data = $this.data('bs.modal') var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option) if (!data) $this.data('bs.modal', (data = new Modal(this, options))) if (typeof option == 'string') data[option](_relatedTarget) else if (options.show) data.show(_relatedTarget) }) } var old = $.fn.modal $.fn.modal = Plugin $.fn.modal.Constructor = Modal // MODAL NO CONFLICT // ================= $.fn.modal.noConflict = function () { $.fn.modal = old return this } // MODAL DATA-API // ============== $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) { var $this = $(this) var href = $this.attr('href') var target = $this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7 var $target = $(document).find(target) var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data()) if ($this.is('a')) e.preventDefault() $target.one('show.bs.modal', function (showEvent) { if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown $target.one('hidden.bs.modal', function () { $this.is(':visible') && $this.trigger('focus') }) }) Plugin.call($target, option, this) }) }(jQuery); /* ======================================================================== * Bootstrap: tooltip.js v3.4.1 * https://getbootstrap.com/docs/3.4/javascript/#tooltip * Inspired by the original jQuery.tipsy by Jason Frame * ======================================================================== * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; var DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn'] var uriAttrs = [ 'background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href' ] var ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i var DefaultWhitelist = { // Global attributes allowed on any supplied element below. '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN], a: ['target', 'href', 'title', 'rel'], area: [], b: [], br: [], col: [], code: [], div: [], em: [], hr: [], h1: [], h2: [], h3: [], h4: [], h5: [], h6: [], i: [], img: ['src', 'alt', 'title', 'width', 'height'], li: [], ol: [], p: [], pre: [], s: [], small: [], span: [], sub: [], sup: [], strong: [], u: [], ul: [] } /** * A pattern that recognizes a commonly useful subset of URLs that are safe. * * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts */ var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi /** * A pattern that matches safe data URLs. Only matches image, video and audio types. * * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts */ var DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i function allowedAttribute(attr, allowedAttributeList) { var attrName = attr.nodeName.toLowerCase() if ($.inArray(attrName, allowedAttributeList) !== -1) { if ($.inArray(attrName, uriAttrs) !== -1) { return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN)) } return true } var regExp = $(allowedAttributeList).filter(function (index, value) { return value instanceof RegExp }) // Check if a regular expression validates the attribute. for (var i = 0, l = regExp.length; i < l; i++) { if (attrName.match(regExp[i])) { return true } } return false } function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) { if (unsafeHtml.length === 0) { return unsafeHtml } if (sanitizeFn && typeof sanitizeFn === 'function') { return sanitizeFn(unsafeHtml) } // IE 8 and below don't support createHTMLDocument if (!document.implementation || !document.implementation.createHTMLDocument) { return unsafeHtml } var createdDocument = document.implementation.createHTMLDocument('sanitization') createdDocument.body.innerHTML = unsafeHtml var whitelistKeys = $.map(whiteList, function (el, i) { return i }) var elements = $(createdDocument.body).find('*') for (var i = 0, len = elements.length; i < len; i++) { var el = elements[i] var elName = el.nodeName.toLowerCase() if ($.inArray(elName, whitelistKeys) === -1) { el.parentNode.removeChild(el) continue } var attributeList = $.map(el.attributes, function (el) { return el }) var whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || []) for (var j = 0, len2 = attributeList.length; j < len2; j++) { if (!allowedAttribute(attributeList[j], whitelistedAttributes)) { el.removeAttribute(attributeList[j].nodeName) } } } return createdDocument.body.innerHTML } // TOOLTIP PUBLIC CLASS DEFINITION // =============================== var Tooltip = function (element, options) { this.type = null this.options = null this.enabled = null this.timeout = null this.hoverState = null this.$element = null this.inState = null this.init('tooltip', element, options) } Tooltip.VERSION = '3.4.1' Tooltip.TRANSITION_DURATION = 150 Tooltip.DEFAULTS = { animation: true, placement: 'top', selector: false, template: '', trigger: 'hover focus', title: '', delay: 0, html: false, container: false, viewport: { selector: 'body', padding: 0 }, sanitize : true, sanitizeFn : null, whiteList : DefaultWhitelist } Tooltip.prototype.init = function (type, element, options) { this.enabled = true this.type = type this.$element = $(element) this.options = this.getOptions(options) this.$viewport = this.options.viewport && $(document).find($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport)) this.inState = { click: false, hover: false, focus: false } if (this.$element[0] instanceof document.constructor && !this.options.selector) { throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!') } var triggers = this.options.trigger.split(' ') for (var i = triggers.length; i--;) { var trigger = triggers[i] if (trigger == 'click') { this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) } else if (trigger != 'manual') { var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) } } this.options.selector ? (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : this.fixTitle() } Tooltip.prototype.getDefaults = function () { return Tooltip.DEFAULTS } Tooltip.prototype.getOptions = function (options) { var dataAttributes = this.$element.data() for (var dataAttr in dataAttributes) { if (dataAttributes.hasOwnProperty(dataAttr) && $.inArray(dataAttr, DISALLOWED_ATTRIBUTES) !== -1) { delete dataAttributes[dataAttr] } } options = $.extend({}, this.getDefaults(), dataAttributes, options) if (options.delay && typeof options.delay == 'number') { options.delay = { show: options.delay, hide: options.delay } } if (options.sanitize) { options.template = sanitizeHtml(options.template, options.whiteList, options.sanitizeFn) } return options } Tooltip.prototype.getDelegateOptions = function () { var options = {} var defaults = this.getDefaults() this._options && $.each(this._options, function (key, value) { if (defaults[key] != value) options[key] = value }) return options } Tooltip.prototype.enter = function (obj) { var self = obj instanceof this.constructor ? obj : $(obj.currentTarget).data('bs.' + this.type) if (!self) { self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) $(obj.currentTarget).data('bs.' + this.type, self) } if (obj instanceof $.Event) { self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true } if (self.tip().hasClass('in') || self.hoverState == 'in') { self.hoverState = 'in' return } clearTimeout(self.timeout) self.hoverState = 'in' if (!self.options.delay || !self.options.delay.show) return self.show() self.timeout = setTimeout(function () { if (self.hoverState == 'in') self.show() }, self.options.delay.show) } Tooltip.prototype.isInStateTrue = function () { for (var key in this.inState) { if (this.inState[key]) return true } return false } Tooltip.prototype.leave = function (obj) { var self = obj instanceof this.constructor ? obj : $(obj.currentTarget).data('bs.' + this.type) if (!self) { self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) $(obj.currentTarget).data('bs.' + this.type, self) } if (obj instanceof $.Event) { self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false } if (self.isInStateTrue()) return clearTimeout(self.timeout) self.hoverState = 'out' if (!self.options.delay || !self.options.delay.hide) return self.hide() self.timeout = setTimeout(function () { if (self.hoverState == 'out') self.hide() }, self.options.delay.hide) } Tooltip.prototype.show = function () { var e = $.Event('show.bs.' + this.type) if (this.hasContent() && this.enabled) { this.$element.trigger(e) var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0]) if (e.isDefaultPrevented() || !inDom) return var that = this var $tip = this.tip() var tipId = this.getUID(this.type) this.setContent() $tip.attr('id', tipId) this.$element.attr('aria-describedby', tipId) if (this.options.animation) $tip.addClass('fade') var placement = typeof this.options.placement == 'function' ? this.options.placement.call(this, $tip[0], this.$element[0]) : this.options.placement var autoToken = /\s?auto?\s?/i var autoPlace = autoToken.test(placement) if (autoPlace) placement = placement.replace(autoToken, '') || 'top' $tip .detach() .css({ top: 0, left: 0, display: 'block' }) .addClass(placement) .data('bs.' + this.type, this) this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element) this.$element.trigger('inserted.bs.' + this.type) var pos = this.getPosition() var actualWidth = $tip[0].offsetWidth var actualHeight = $tip[0].offsetHeight if (autoPlace) { var orgPlacement = placement var viewportDim = this.getPosition(this.$viewport) placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' : placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' : placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' : placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' : placement $tip .removeClass(orgPlacement) .addClass(placement) } var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) this.applyPlacement(calculatedOffset, placement) var complete = function () { var prevHoverState = that.hoverState that.$element.trigger('shown.bs.' + that.type) that.hoverState = null if (prevHoverState == 'out') that.leave(that) } $.support.transition && this.$tip.hasClass('fade') ? $tip .one('bsTransitionEnd', complete) .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : complete() } } Tooltip.prototype.applyPlacement = function (offset, placement) { var $tip = this.tip() var width = $tip[0].offsetWidth var height = $tip[0].offsetHeight // manually read margins because getBoundingClientRect includes difference var marginTop = parseInt($tip.css('margin-top'), 10) var marginLeft = parseInt($tip.css('margin-left'), 10) // we must check for NaN for ie 8/9 if (isNaN(marginTop)) marginTop = 0 if (isNaN(marginLeft)) marginLeft = 0 offset.top += marginTop offset.left += marginLeft // $.fn.offset doesn't round pixel values // so we use setOffset directly with our own function B-0 $.offset.setOffset($tip[0], $.extend({ using: function (props) { $tip.css({ top: Math.round(props.top), left: Math.round(props.left) }) } }, offset), 0) $tip.addClass('in') // check to see if placing tip in new offset caused the tip to resize itself var actualWidth = $tip[0].offsetWidth var actualHeight = $tip[0].offsetHeight if (placement == 'top' && actualHeight != height) { offset.top = offset.top + height - actualHeight } var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) if (delta.left) offset.left += delta.left else offset.top += delta.top var isVertical = /top|bottom/.test(placement) var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight' $tip.offset(offset) this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical) } Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) { this.arrow() .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%') .css(isVertical ? 'top' : 'left', '') } Tooltip.prototype.setContent = function () { var $tip = this.tip() var title = this.getTitle() if (this.options.html) { if (this.options.sanitize) { title = sanitizeHtml(title, this.options.whiteList, this.options.sanitizeFn) } $tip.find('.tooltip-inner').html(title) } else { $tip.find('.tooltip-inner').text(title) } $tip.removeClass('fade in top bottom left right') } Tooltip.prototype.hide = function (callback) { var that = this var $tip = $(this.$tip) var e = $.Event('hide.bs.' + this.type) function complete() { if (that.hoverState != 'in') $tip.detach() if (that.$element) { // TODO: Check whether guarding this code with this `if` is really necessary. that.$element .removeAttr('aria-describedby') .trigger('hidden.bs.' + that.type) } callback && callback() } this.$element.trigger(e) if (e.isDefaultPrevented()) return $tip.removeClass('in') $.support.transition && $tip.hasClass('fade') ? $tip .one('bsTransitionEnd', complete) .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : complete() this.hoverState = null return this } Tooltip.prototype.fixTitle = function () { var $e = this.$element if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') { $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') } } Tooltip.prototype.hasContent = function () { return this.getTitle() } Tooltip.prototype.getPosition = function ($element) { $element = $element || this.$element var el = $element[0] var isBody = el.tagName == 'BODY' var elRect = el.getBoundingClientRect() if (elRect.width == null) { // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093 elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top }) } var isSvg = window.SVGElement && el instanceof window.SVGElement // Avoid using $.offset() on SVGs since it gives incorrect results in jQuery 3. // See https://github.com/twbs/bootstrap/issues/20280 var elOffset = isBody ? { top: 0, left: 0 } : (isSvg ? null : $element.offset()) var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() } var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null return $.extend({}, elRect, scroll, outerDims, elOffset) } Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } } Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { var delta = { top: 0, left: 0 } if (!this.$viewport) return delta var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 var viewportDimensions = this.getPosition(this.$viewport) if (/right|left/.test(placement)) { var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight if (topEdgeOffset < viewportDimensions.top) { // top overflow delta.top = viewportDimensions.top - topEdgeOffset } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset } } else { var leftEdgeOffset = pos.left - viewportPadding var rightEdgeOffset = pos.left + viewportPadding + actualWidth if (leftEdgeOffset < viewportDimensions.left) { // left overflow delta.left = viewportDimensions.left - leftEdgeOffset } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset } } return delta } Tooltip.prototype.getTitle = function () { var title var $e = this.$element var o = this.options title = $e.attr('data-original-title') || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) return title } Tooltip.prototype.getUID = function (prefix) { do prefix += ~~(Math.random() * 1000000) while (document.getElementById(prefix)) return prefix } Tooltip.prototype.tip = function () { if (!this.$tip) { this.$tip = $(this.options.template) if (this.$tip.length != 1) { throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!') } } return this.$tip } Tooltip.prototype.arrow = function () { return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')) } Tooltip.prototype.enable = function () { this.enabled = true } Tooltip.prototype.disable = function () { this.enabled = false } Tooltip.prototype.toggleEnabled = function () { this.enabled = !this.enabled } Tooltip.prototype.toggle = function (e) { var self = this if (e) { self = $(e.currentTarget).data('bs.' + this.type) if (!self) { self = new this.constructor(e.currentTarget, this.getDelegateOptions()) $(e.currentTarget).data('bs.' + this.type, self) } } if (e) { self.inState.click = !self.inState.click if (self.isInStateTrue()) self.enter(self) else self.leave(self) } else { self.tip().hasClass('in') ? self.leave(self) : self.enter(self) } } Tooltip.prototype.destroy = function () { var that = this clearTimeout(this.timeout) this.hide(function () { that.$element.off('.' + that.type).removeData('bs.' + that.type) if (that.$tip) { that.$tip.detach() } that.$tip = null that.$arrow = null that.$viewport = null that.$element = null }) } Tooltip.prototype.sanitizeHtml = function (unsafeHtml) { return sanitizeHtml(unsafeHtml, this.options.whiteList, this.options.sanitizeFn) } // TOOLTIP PLUGIN DEFINITION // ========================= function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.tooltip') var options = typeof option == 'object' && option if (!data && /destroy|hide/.test(option)) return if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) if (typeof option == 'string') data[option]() }) } var old = $.fn.tooltip $.fn.tooltip = Plugin $.fn.tooltip.Constructor = Tooltip // TOOLTIP NO CONFLICT // =================== $.fn.tooltip.noConflict = function () { $.fn.tooltip = old return this } }(jQuery); /* ======================================================================== * Bootstrap: popover.js v3.4.1 * https://getbootstrap.com/docs/3.4/javascript/#popovers * ======================================================================== * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // POPOVER PUBLIC CLASS DEFINITION // =============================== var Popover = function (element, options) { this.init('popover', element, options) } if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js') Popover.VERSION = '3.4.1' Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, { placement: 'right', trigger: 'click', content: '', template: '' }) // NOTE: POPOVER EXTENDS tooltip.js // ================================ Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype) Popover.prototype.constructor = Popover Popover.prototype.getDefaults = function () { return Popover.DEFAULTS } Popover.prototype.setContent = function () { var $tip = this.tip() var title = this.getTitle() var content = this.getContent() if (this.options.html) { var typeContent = typeof content if (this.options.sanitize) { title = this.sanitizeHtml(title) if (typeContent === 'string') { content = this.sanitizeHtml(content) } } $tip.find('.popover-title').html(title) $tip.find('.popover-content').children().detach().end()[ typeContent === 'string' ? 'html' : 'append' ](content) } else { $tip.find('.popover-title').text(title) $tip.find('.popover-content').children().detach().end().text(content) } $tip.removeClass('fade top bottom left right in') // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do // this manually by checking the contents. if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide() } Popover.prototype.hasContent = function () { return this.getTitle() || this.getContent() } Popover.prototype.getContent = function () { var $e = this.$element var o = this.options return $e.attr('data-content') || (typeof o.content == 'function' ? o.content.call($e[0]) : o.content) } Popover.prototype.arrow = function () { return (this.$arrow = this.$arrow || this.tip().find('.arrow')) } // POPOVER PLUGIN DEFINITION // ========================= function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.popover') var options = typeof option == 'object' && option if (!data && /destroy|hide/.test(option)) return if (!data) $this.data('bs.popover', (data = new Popover(this, options))) if (typeof option == 'string') data[option]() }) } var old = $.fn.popover $.fn.popover = Plugin $.fn.popover.Constructor = Popover // POPOVER NO CONFLICT // =================== $.fn.popover.noConflict = function () { $.fn.popover = old return this } }(jQuery); /* ======================================================================== * Bootstrap: scrollspy.js v3.4.1 * https://getbootstrap.com/docs/3.4/javascript/#scrollspy * ======================================================================== * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // SCROLLSPY CLASS DEFINITION // ========================== function ScrollSpy(element, options) { this.$body = $(document.body) this.$scrollElement = $(element).is(document.body) ? $(window) : $(element) this.options = $.extend({}, ScrollSpy.DEFAULTS, options) this.selector = (this.options.target || '') + ' .nav li > a' this.offsets = [] this.targets = [] this.activeTarget = null this.scrollHeight = 0 this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this)) this.refresh() this.process() } ScrollSpy.VERSION = '3.4.1' ScrollSpy.DEFAULTS = { offset: 10 } ScrollSpy.prototype.getScrollHeight = function () { return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight) } ScrollSpy.prototype.refresh = function () { var that = this var offsetMethod = 'offset' var offsetBase = 0 this.offsets = [] this.targets = [] this.scrollHeight = this.getScrollHeight() if (!$.isWindow(this.$scrollElement[0])) { offsetMethod = 'position' offsetBase = this.$scrollElement.scrollTop() } this.$body .find(this.selector) .map(function () { var $el = $(this) var href = $el.data('target') || $el.attr('href') var $href = /^#./.test(href) && $(href) return ($href && $href.length && $href.is(':visible') && [[$href[offsetMethod]().top + offsetBase, href]]) || null }) .sort(function (a, b) { return a[0] - b[0] }) .each(function () { that.offsets.push(this[0]) that.targets.push(this[1]) }) } ScrollSpy.prototype.process = function () { var scrollTop = this.$scrollElement.scrollTop() + this.options.offset var scrollHeight = this.getScrollHeight() var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height() var offsets = this.offsets var targets = this.targets var activeTarget = this.activeTarget var i if (this.scrollHeight != scrollHeight) { this.refresh() } if (scrollTop >= maxScroll) { return activeTarget != (i = targets[targets.length - 1]) && this.activate(i) } if (activeTarget && scrollTop < offsets[0]) { this.activeTarget = null return this.clear() } for (i = offsets.length; i--;) { activeTarget != targets[i] && scrollTop >= offsets[i] && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1]) && this.activate(targets[i]) } } ScrollSpy.prototype.activate = function (target) { this.activeTarget = target this.clear() var selector = this.selector + '[data-target="' + target + '"],' + this.selector + '[href="' + target + '"]' var active = $(selector) .parents('li') .addClass('active') if (active.parent('.dropdown-menu').length) { active = active .closest('li.dropdown') .addClass('active') } active.trigger('activate.bs.scrollspy') } ScrollSpy.prototype.clear = function () { $(this.selector) .parentsUntil(this.options.target, '.active') .removeClass('active') } // SCROLLSPY PLUGIN DEFINITION // =========================== function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.scrollspy') var options = typeof option == 'object' && option if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options))) if (typeof option == 'string') data[option]() }) } var old = $.fn.scrollspy $.fn.scrollspy = Plugin $.fn.scrollspy.Constructor = ScrollSpy // SCROLLSPY NO CONFLICT // ===================== $.fn.scrollspy.noConflict = function () { $.fn.scrollspy = old return this } // SCROLLSPY DATA-API // ================== $(window).on('load.bs.scrollspy.data-api', function () { $('[data-spy="scroll"]').each(function () { var $spy = $(this) Plugin.call($spy, $spy.data()) }) }) }(jQuery); /* ======================================================================== * Bootstrap: tab.js v3.4.1 * https://getbootstrap.com/docs/3.4/javascript/#tabs * ======================================================================== * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // TAB CLASS DEFINITION // ==================== var Tab = function (element) { // jscs:disable requireDollarBeforejQueryAssignment this.element = $(element) // jscs:enable requireDollarBeforejQueryAssignment } Tab.VERSION = '3.4.1' Tab.TRANSITION_DURATION = 150 Tab.prototype.show = function () { var $this = this.element var $ul = $this.closest('ul:not(.dropdown-menu)') var selector = $this.data('target') if (!selector) { selector = $this.attr('href') selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 } if ($this.parent('li').hasClass('active')) return var $previous = $ul.find('.active:last a') var hideEvent = $.Event('hide.bs.tab', { relatedTarget: $this[0] }) var showEvent = $.Event('show.bs.tab', { relatedTarget: $previous[0] }) $previous.trigger(hideEvent) $this.trigger(showEvent) if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return var $target = $(document).find(selector) this.activate($this.closest('li'), $ul) this.activate($target, $target.parent(), function () { $previous.trigger({ type: 'hidden.bs.tab', relatedTarget: $this[0] }) $this.trigger({ type: 'shown.bs.tab', relatedTarget: $previous[0] }) }) } Tab.prototype.activate = function (element, container, callback) { var $active = container.find('> .active') var transition = callback && $.support.transition && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length) function next() { $active .removeClass('active') .find('> .dropdown-menu > .active') .removeClass('active') .end() .find('[data-toggle="tab"]') .attr('aria-expanded', false) element .addClass('active') .find('[data-toggle="tab"]') .attr('aria-expanded', true) if (transition) { element[0].offsetWidth // reflow for transition element.addClass('in') } else { element.removeClass('fade') } if (element.parent('.dropdown-menu').length) { element .closest('li.dropdown') .addClass('active') .end() .find('[data-toggle="tab"]') .attr('aria-expanded', true) } callback && callback() } $active.length && transition ? $active .one('bsTransitionEnd', next) .emulateTransitionEnd(Tab.TRANSITION_DURATION) : next() $active.removeClass('in') } // TAB PLUGIN DEFINITION // ===================== function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.tab') if (!data) $this.data('bs.tab', (data = new Tab(this))) if (typeof option == 'string') data[option]() }) } var old = $.fn.tab $.fn.tab = Plugin $.fn.tab.Constructor = Tab // TAB NO CONFLICT // =============== $.fn.tab.noConflict = function () { $.fn.tab = old return this } // TAB DATA-API // ============ var clickHandler = function (e) { e.preventDefault() Plugin.call($(this), 'show') } $(document) .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler) .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler) }(jQuery); /* ======================================================================== * Bootstrap: affix.js v3.4.1 * https://getbootstrap.com/docs/3.4/javascript/#affix * ======================================================================== * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // AFFIX CLASS DEFINITION // ====================== var Affix = function (element, options) { this.options = $.extend({}, Affix.DEFAULTS, options) var target = this.options.target === Affix.DEFAULTS.target ? $(this.options.target) : $(document).find(this.options.target) this.$target = target .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this)) .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this)) this.$element = $(element) this.affixed = null this.unpin = null this.pinnedOffset = null this.checkPosition() } Affix.VERSION = '3.4.1' Affix.RESET = 'affix affix-top affix-bottom' Affix.DEFAULTS = { offset: 0, target: window } Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) { var scrollTop = this.$target.scrollTop() var position = this.$element.offset() var targetHeight = this.$target.height() if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false if (this.affixed == 'bottom') { if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom' return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom' } var initializing = this.affixed == null var colliderTop = initializing ? scrollTop : position.top var colliderHeight = initializing ? targetHeight : height if (offsetTop != null && scrollTop <= offsetTop) return 'top' if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom' return false } Affix.prototype.getPinnedOffset = function () { if (this.pinnedOffset) return this.pinnedOffset this.$element.removeClass(Affix.RESET).addClass('affix') var scrollTop = this.$target.scrollTop() var position = this.$element.offset() return (this.pinnedOffset = position.top - scrollTop) } Affix.prototype.checkPositionWithEventLoop = function () { setTimeout($.proxy(this.checkPosition, this), 1) } Affix.prototype.checkPosition = function () { if (!this.$element.is(':visible')) return var height = this.$element.height() var offset = this.options.offset var offsetTop = offset.top var offsetBottom = offset.bottom var scrollHeight = Math.max($(document).height(), $(document.body).height()) if (typeof offset != 'object') offsetBottom = offsetTop = offset if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element) if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element) var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom) if (this.affixed != affix) { if (this.unpin != null) this.$element.css('top', '') var affixType = 'affix' + (affix ? '-' + affix : '') var e = $.Event(affixType + '.bs.affix') this.$element.trigger(e) if (e.isDefaultPrevented()) return this.affixed = affix this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null this.$element .removeClass(Affix.RESET) .addClass(affixType) .trigger(affixType.replace('affix', 'affixed') + '.bs.affix') } if (affix == 'bottom') { this.$element.offset({ top: scrollHeight - height - offsetBottom }) } } // AFFIX PLUGIN DEFINITION // ======================= function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.affix') var options = typeof option == 'object' && option if (!data) $this.data('bs.affix', (data = new Affix(this, options))) if (typeof option == 'string') data[option]() }) } var old = $.fn.affix $.fn.affix = Plugin $.fn.affix.Constructor = Affix // AFFIX NO CONFLICT // ================= $.fn.affix.noConflict = function () { $.fn.affix = old return this } // AFFIX DATA-API // ============== $(window).on('load', function () { $('[data-spy="affix"]').each(function () { var $spy = $(this) var data = $spy.data() data.offset = data.offset || {} if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom if (data.offsetTop != null) data.offset.top = data.offsetTop Plugin.call($spy, data) }) }) }(jQuery); ================================================ FILE: doc/_build/manual/alt_layouts.html ================================================ Alt Layouts

Alt Layouts are for when you want to create more than one physical .html file per .md file. This is most useful when the additional .html files do not depend on the content of the original page, but on the front matter attributes.

Usage

To enable alt layouts for a .md file, add an alt_layouts attribute to the front matter of a page. This is a list of objects containing two attributes, layout and location.

The layout attribute gives the name of an alternate layout to use. The location attribute gives the directory where the .html file should be put. That directory must already exist in your directory structure.

Also add either items_index or items_filter to say where the list of it

Example

The following is a sample of generating two additional .html files for a product page:

layout: product

alt_layouts:
    - layout: confirmation
      location: confirmations
    - layout: product_details
      location: details

If the original foo.md file was in the products directory, three .html files would be generated:

products/foo.html
confirmations/foo.html
details/foo.html
================================================ FILE: doc/_build/manual/authoring.html ================================================ Authoring

Content

In Urubu, content is entered in Markdown format. This is a lightweight format that feels like a natural way to write content in plain text.

Stock markdown has a small feature set. For example, it does not even support tables. For this reason, Urubu supports some extensions. In particular, it supports the Markdown Extra extensions that have become an industry standard, as well as a few others.

The most notable supported extensions are:

Code

Urubu intents to offer good support for software projects. Therefore, it supports nicely rendered code blocks.

One part of the solution is Fenced Code Blocks, provided by the Markdown Extra extensions. This lets you enter language-specific code blocks without the need for indentation.

The second part is the CodeHilite extension of Python-Markdown. This extension enables language-specific syntax highlighting through the Pygments library.

To properly render the highlighted code, you will need to add a syntax.css stylesheet. A good solution is to use the syntax stylesheet from GitHub.

Stock Markdown supports "reference links" that are resolved by defining them later in the file. For example, you can use [urubu] in your content and further on define it as follows:

[urubu]: http://urubu.jandecaluwe.com

This is nice for readability, but it all remains file based.

Urubu extends this behavior by automatically resolving Project-wide reference ids. This feature is implemented as a Markdown extension. Note that it doesn't require a syntax change. It enables page linking like in wikis.

In addition, you can add a fragment, like #some-anchor, to the reference id. This represents a link to an anchor within a page. Since Urubu automatically adds slugified anchors to markdown headers, you can use those as targets. For instance, [authoring#reference-links] is a link to the current Reference links section. You can also define your own anchors using Attribute lists.

Markdown supports reference links without a text. In that case, Urubu inserts an appropriate text in the html. For a reference link with no fragment, the title of the page is inserted. For a reference link with a fragment, the fragment text is inserted. To make the result more readable, you can use non-slugified fragment text. For example, [authoring#Reference links] also links to the present section, and is rendered as Reference links.

================================================ FILE: doc/_build/manual/building.html ================================================ Project building

The urubu command

After installation, an urubu command will be available.

If you prefer, you can call the installed package as a script using python -m urubu, with the same effect.

Subcommands

The urubu command supports two subcommands. Run these commands from the top level project directory.

urubu build
Build the website. The website will be in the _build subdirectory.
urubu serve
Start a local webserver to serve the website as you develop it. The website will be available at localhost:8000. Run this command in a separate terminal window, and kill the server when you are done.

Development flow

I prefer to put the commands in a Makefile, so that I can run make to build and make serve to start a server.

Currently, you have to build the site explicitly to see the development changes in the browser.

================================================ FILE: doc/_build/manual/extensions.html ================================================ Markdown extensions

Introduction

Urubu implements a number of Markdown extensions. These extensions do not change or extend the Markdown syntax. Rather, they add interesting features by processing and rendering the Markdown source in more sophisticated ways.

The extensions are described in more detail below.

Project-wide reference ids

Urubu implements a Markdown extension to resolve project-wide reference ids. This means that all pages in the project are automatically available as reference ids, and can be referred to using Markdown's syntax for reference links.

This feature is described in more detail in the sections Project-wide reference ids and Reference links. It is Urubu's most important extension and a fundamental feature of the tool.

Bootstrap-specific extensions

Urubu is designed to play well with Bootstrap. To use certain Bootstrap features, it has extensions that add Bootstrap classes to certain tags. More specifically, the following classes are added:

table
Added to the <table> tag. This defines basic styling for tables.
dl-horizontal
Added to the <dl> tag that defines definition lists. This creates a horizontal layout for definition lists in wide viewports.

Support for the mark tag

The html5 specification added a new tag to highlight text: the <mark> tag. For a good explanation of its purpose and the differences with the <strong> and <em> tags, see this answer on Stack Overflow.

Urubu supports lightweight markup for this tag by taking advantage of a redundancy in Markdown. In standard Markdown, you can either use asterisks (*) or underscores (_) to indicate emphasis. With the Urubu extension, the underscore (_) version is rendered using <mark> instead.

This is an experimental feature that may be taken out if there are serious objections, although at this point there do not seem to be disadvantages. To disable the feature, the mark_tag_support variable can be set to false in the _site.yml file.

================================================ FILE: doc/_build/manual/hooks.html ================================================ Python hooks

Introduction

Urubu supports Python hooks to make templating easier. Upon a build, it tries to import a _python module or package, and looks for hook variables with predefined names. The following hooks are defined:

Variable Description
filters A mapping from filter names to filter functions.
process_info A function to inspect and process content file info.

You have to make sure that these names are exported correctly. For example, if you organize _python as a package, it could look as follows:

_python/
    __init__.py
    filters.py
    hooks.py

If filters is defined in filters.py, and process_info in hooks.py, the __init__.py file would contain:

from .filters import filters
from .hooks import process_info

The filters hook

Filters functions should be defined as custom filters in Jinja2.

As a typical example, consider a filter that converts a date value into a desired format. The filters.py module would contain the following:

def dateformat(value, format="%d-%b-%Y"):
    return value.strftime(format)

filters = {}
filters['dateformat'] = dateformat

You can then use the dateformat filter in templates.

The process_info hook

The interface of the process_info function is as follows:

def process(info, site):
    ...

This function is called for every content file in the project.

The site variable provides access to the site variables defined in _site.yml.

The info variable contains the file content info as it is being constructed by Urubu. At the moment of the call, the following inferred attributes are available:

Attribute Description
id The unique id by which the object is known in the project.
url The url of the object.
components The components of the object's pathname, without file extension, as a list.
fn The pathname of the file or directory corresponding the object.
mdate Modification date

In addition, all attributes specified in the YAML front matter of the corresponding content file are available as attributes of the info object.

The site and info variables are Python dictionaries. This means that the attributes are available via key access, not via Python attribute access. This is because the YAML reader constructs Python dictionaries from the front matter.

The process_info function can can inspect the attributes, verify and modify them, and add additional ones.

process_info examples

Defining a default layout

It can be handy to define a default layout for the case this mandatory attribute is not specified in the content file. Suppose we want a default index layout for index files, and a page layout for other files:

def process_info(info, site):
    if 'layout' not in info:
        if info['components'][-1] == 'index':
            info['layout'] = 'index'
        else:
            info['layout'] = 'page'

Defining a specific layout

Suppose we have a blog directory and we want to automatically define a specific post layout for blog posts:

def process_info(info, site):
    components = info['components']
    if len(components) == 2:
        if components[0] == 'blog' and components[1] != 'index':
            process_post(info)

def process_post(info):
    if not 'layout' in info:
        info['layout'] = 'post'
================================================ FILE: doc/_build/manual/index.html ================================================ Manual

Manual

================================================ FILE: doc/_build/manual/install.html ================================================ Installation

Urubu works with modern versions of Python 2 and Python 3 using the same codebase. More specifically, it requires Python 2.7 or Python 3.4.

You can install Urubu using pip:

pip install urubu

To upgrade an existing installation to the latest version, use:

pip install --upgrade urubu

If pip is not yet available on your system, follow the pip installation instructions.

You may want to install Urubu in an isolated environment using virtualenv.

Urubu depends on a number of libraries that will automatically be installed if not yet available: Python-Markdown, PyYAML, Pygments and Jinja2.

For a quick way to set up a new Urubu project, visit Urubu Quickstart.

================================================ FILE: doc/_build/manual/intro.html ================================================ Concepts

Introduction

Welcome to Urubu! My name is Jan Decaluwe and I am Urubu's author.

Urubu is a micro CMS for static websites. The qualification "micro* means that it has a small feature set, defined by what I need for my purposes. To know whether it is the right tool for you, check out Overview.

Urubu's design philosophy is radical reuse of great software and ideas from others. In the following sections, I will describe its concepts and how they are implemented.

Authoring

In Urubu, content is entered in Markdown format. This is a lightweight format that feels like a natural way to write content in plain text.

Markdown support in Urubu is implemented by the Python-Markdown package, that converts the format to html. Urubu also supports the industry standard Markdown Extra extensions, with useful features such as tables and definition lists.

Urubu supports nicely rendered code blocks, an essential feature for software projects documentation. Fenced Code Blocks are provided by the Markdown Extra extensions. This lets you enter language-specific code blocks without the need for indentation. The CodeHilite extension of Python-Markdown enables language-specific syntax highlighting via the Pygments library.

Configuration

The configuration options in Urubu are kept minimal, in the spirit of "There should be one obvious way to do it". Where used, the configuration format is YAML, implemented by the PyYAML library.

Configuration is mostly distributed, in the sense that every content file should have a front matter, that specifies the title, layout, date and so on. This idea is found in many tools, but Urubu reuses the technique from Jekyll. YAML front matter is specified between two sets of triple dashes.

Urubu extends this configuration technique by treating index files specially. Each folder in the site should have an index file (called index.md) that specifies the ordered folder content. This can be done explicitly by listing the files, or implicitly by specifying how the files should be ordered.

Templating

With templates you specify the html layout for a particular type of a page. In a template you can mix plain html with control structures and variable interpolation. The actual html page is generated by evaluating the template with the appropriate evaluation context provided by Urubu.

Urubu uses the Jinja2 templating language library.

Theming

A theme refers to the general look and feel of a web site. Partially this is defined by the templates as discussed above. The other part is defined in style sheets, with a technique known as Cascading Style Sheets (CSS). Basically this is a sophisticated technique to define how the various html elements should be rendered by the web browser.

With Urubu, you are free to design and use your own style sheets. However, it has been developed with Bootstrap in mind. Bootstrap is a professionally-designed framework with lots of useful predefined styles components. Urubu generates html that is Bootstrap-friendly, and infers the appropriate template variables for certain Bootstrap components.

A great feature of Bootstrap is that it is "mobile first". This means that your website will automatically adapt to any platform - smartphone, tablet or widescreen.

A notable project is Bootswatch. This is a set of themes designed as drop-in replacement for the stock bootstrap styles. This gives you an effortless option to change the look and feel of your website.

I am a big fan of Steve Krug's book Don't make me think, and I feel that the lessons from this book are still often ignored. Actually, the lack of focus of other tools on these ideas are the main reason why I wrote Urubu.

A main concept is good navigation. Urubu supports various techniques by inferring navigation-oriented variables and making them available to the template engine. Moreover, they work well with some well-defined and nicely style Bootstrap navigation components. In this way, you can easily implement the following:

  • a navbar for navigation between major sections
  • table of contents of a page in a sidebar
  • breadcrumbs
  • previous and next pager buttons
  • active page or section highlighting

Other techniques, independent from Urubu, can also help. Note for example that the sidebar on this page is "affixed": it moves as you scroll through the page, but never leaves the viewport. (Note: this description assumes that the viewport is wide enough to accomodate the sidebar.) At any time, the full structure of the page remains visible and available for navigation. This was implemented by borrowing code from the Bootstrap theme.

Project-wide reference ids

Markdown defines the concept of a reference link. This is a way to refer to a page or an url using a reference id. The syntax of a reference link is a reference id between square brackets, for example [intro].

Urubu supports the concept of project-wide reference ids. First, global reference ids can be defined in the site configuration file. Moreover, all content pages and folders have a corresponding reference id: their pathname without extension. In this case, reference links are similar to wiki links, the typical way to link between pages in wiki's.

Standard Markdown only resolves reference ids that are defined within the file. Urubu extends this behavior by resolving them over the project. This feature is implemented as a Markdown extension. Note that it doesn't require new syntax.

Project-wide reference ids are a unique Urubu feature.

One of the messages of Steve Krug's book is that the text that you click should be the title of the page where you land. Therefore, when you use reference links, Urubu will insert the page title in the generated html (unless you specify an alternative text explicitly).

Development and deployment

You can develop a Urubu project is like a software project, from a git or mercurial repository. This gives you best-in-class revision control. Moreover, all the workflows that these systems provide are available. For example, you can develop your website collaboratively on GitHub or Bitbucket. Finally, it is easy to automate deployment, triggered by a push of the generated site to an upstream repository.

================================================ FILE: doc/_build/manual/pagination.html ================================================ Pagination

There are times when an index file will contain more entries than you want to include in a single page. Pagination allows Urubu to automatically split that page into separate pages in your site.

Usage

To enable pagination, add an items_per_page attribute to the front matter of an index page. Also add either items_index or items_filter to say where the list of items should pull from.

To pull from files in the current directory, with 5 items per page:

items_per_page: 5
items_index: this

To pull from a different index contents:

items_per_page: 5
items_index: news\index.md

To filter the contents:

items_per_page: 5
items_filter: mysteries time-loop

New Page Variables

Each of the pages generated by pagination will have three new variables available to layouts.

numpages - the number of total pages generated
prevpage - the previous page in the chain
nextpage - the next page in the chain

Example pagination controls

The following is a sample of generating pagination controls in a layout:


================================================ FILE: doc/_build/manual/search.html ================================================ Adding Search

Introduction

A static site cannot natively support dynamic services. Fortunately, it is often an elegant solution to integrate third party solutions within a static site.

One of the most prominent examples is Search. One possibility is integrating an external service such as Google Custom Search. The disadvantage is that one has either to pay for it or accept the branding.

As an alternative, Urubu supports Tipue Search, an open source solution based on javascript executed in the browser. As part of the site building, Urubu generates a view on the searchable content. In this chapter, we describe how the integration is accomplished.

The first step is to download the Tipue Search distribution. It contains a tipuesearch directory. Copy that directory to the top level of your project. As usual, Urubu copies it to the built website, so that the required stylesheets and javascript files are available in the expected location.

Do not rename the tipuesearch directory. The existence of that directory triggers Urubu's support.

The next step is to create a search box. Suppose you want to make it part of the navbar, as in the present site. This is achieved with the following html code:

<form class="navbar-form navbar-left" action="/search.html" role="search">
  <div class="form-group">
    <input type="text" required name="q" id="tipue_search_input" class="form-control" placeholder="Search"> 
   </div>
</form>

The name and the id values in the <input> tag of the search box are mandatory for Tipue Search. The typical place for this code would be in the navbar code in a basic layout for the site.

The search results page

The next step is to create a search result page. To integrate it we first create a dedicated layout using template inheritance. Let us assume that is there is a head_addon and a body_addon block to add links and scripts to the <head and the <body> section respectively. The search.html layout is then as follows:

{% extends "page.html" %}

{% block head_addon %}
<link href="tipuesearch/tipuesearch.css" rel="stylesheet">
{% endblock %}

{% block body_addon %}
<script src="tipuesearch/tipuesearch_content.js"></script>
<script src="tipuesearch/tipuesearch_set.js"></script>
<script src="tipuesearch/tipuesearch.min.js"></script>
<script>
$(document).ready(function() {
     $('#tipue_search_input').tipuesearch({
          'mode': 'json',
          'contentLocation': 'tipuesearch/tipuesearch_content.json' 
     });
});
</script>
{% endblock %}

We inherit from a page.html layout. In the head_addon block, we add the Tipue Search style sheet for the result page. In the body_addon page we add the Tipue Search java script modules, and the inline script that generates the results.

This setup assumes that the jQuery javascript library itself is already loaded in the body of the parent layout, with a line like the following:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>

If you use the Bootstrap javascript modules, that will be the case.

In the top level project directory, we can then create a search.md files that uses the search.html layout and has the generated search results as its content:

---
title: Search results
layout: search
---

<div id="tipue_search_content"></div>

After building the site, there will be a functional search.html file in the top-level directory.

Note The tipuesearch.css stylesheet also contains styling for the search box. The result may be undesirable if you use your own styling, like in the present website. The workaround is to comment the search box styling out.

The search content

The searchable content itself is a JSON object defined in the file tipuesearch/tipuesearch_content.json. This is where Urubu kicks in: this file is generated automatically.

Extracting meaningful searchable content from a web site is not trivial. A design decision for Urubu was to use modern techniques to help with this. In particular, Urubu will only consider content that is wrapped with the <main> tag. This is a relatively new html5 tag with exactly the purpose to indicate the page content explicitly.

The site designer should therefore review the site layouts and wrap all searchable content with the <main> tag. Typically, this is the region were the this.body variable is called in a template.

Note The <main> tag is not supported in IE11. A popular workaround is to use the html5shiv.js Javascript module. Layouts based on Bootstrap do this already.

================================================ FILE: doc/_build/manual/structure.html ================================================ Project structure

The project directory

A typical Urubu project directory looks as follows:

Makefile
_site.yml
_layouts/_base.html
         page.html
         ...
_python/__init__.py
        validators.py
        filters.py
css/...
js/...
index.md
folder1/index.md
        file1.md
        pic1.png
        ...
folder2/index.md
        file2.md
        file3.md
        ...

Files and directories with pathnames starting with an underscore _ are special. They are used during processing, but excluded from the built website. Their function will be discussed below.

The css and js directories are just an example of how CSS style sheets and javascript files could be organized. You can use any organization that you prefer.

Content files are in Markdown format and should have the .md extension. You have complete freedom in organizing them in directories. However, every directory should have an index.md file, including the top-level directory.

Processing rules

Urubu generates a website by processing the files and directory in the project directory, and putting the result in a _build subdirectory. The processing depends on the pathname as follows:

  • a Makefile is ignored and not copied to the build.

  • files and directories starting with a dot . or underscore _ are ignored and not copied to the build.

  • Markdown files with extension .md are converted to a html file that is put into the build in the same relative location.

  • all other files and directories are copied unmodified to the build in the same relative location.

As a result of the project organization and the build process, the structure of the build matches the structure of the project directory. The relative location of all files is thus preserved.

Special files and directories

_site.yml

This file contains site configuration info in YAML format. Currently, these are the predefined attributes:

Attribute Description
reflinks Holds a mapping from reference ids to link objects.
baseurl Prefix for generated local URLs
file_ext Change default file extension ('.html') for processed .md files
link_ext Change default file extension ('.html') for links to site's pages
ignore_patterns List of additional file names or globs to be ignored during processing
keep_files List of explicit file names be kept, overriding any ignores
strict_undefined Set the default behavior regarding undefined template variables

Link objects, for the reflinks attribute, are a mapping with an url key that maps to the link URL and a title key that maps to the link title.

The baseurl option mirrors the same feature in Jekyll. It allows you to specify a prefix for all local URLs generated within your site. This is necessary when your site will be served from a URL that has more than just the hostname. For example, on GitHub Pages sites are served from http://username.github.io/project_name/, so Urubu needs to include that /project_name/ in generated URLs pointing to local content.

baseurl should be specified with no beginning or trailing slashes, e.g.:

baseurl: prefix

The file extension attributes, file_ext and link_ext, are both usually set to the same value (i.e. '.php'), unless the target site has .htaccess rewrite rules that affect the file extensions.

Examples of this are sites that internally redirect pages like www.test.com/account to www.test.com/account.htm. For this case, one would need to set file_ext to '.htm', so Urubu generated files have the .htm extension, whereas link_ext would be set to '', so that the a href links are directed to the files without extension.

Otherwise, file_ext and link_ext should be set to the same extension, specially during testing, so that the simple web server invoked by urubu serve works fine, as well as any web server that does not rewrite the file extensions of the requests.

The ignore_patterns attribute specifies glob-style patterns to be ignored during processing, in addition to the default ones according to the Processing Rules.

In some cases you may explicitly want to keep certain files that would normally be ignored. For example, you may have hidden files like .nojekyll to prevent Jekyll processing, or .htaccess and .htpasswd for access control. You can keep such files in the build using the keep_files attribute.

The strict_undefined attribute controls whether the build should silently ignore undefined template variables or raise an error when they are encountered. If false or undefined, undefined template variables are treated as empty strings (''). If true, the build will stop and raise an error.

You can define additional attributes that will be made available as site variables to the template engine. The following is an example of a _site.yml file:

brand: Urubu

reflinks:
    content_license:
        url: http://creativecommons.org/licenses/by-sa/3.0/
        title: CC-BY-SA License
    software_license:
        url: http://www.gnu.org/licenses/agpl-3.0.txt
        title: GNU Affero General Public License
    markdown:
        url: http://daringfireball.net/projects/markdown/
        title: Markdown

file_ext: '.htm'  # Change default file extension ('.html')
link_ext: '.htm'  # Change default link extension ('.html')

_layouts

This directory contains the available layouts. They are used by the Jinja2 template engine to render html pages. The layout files should have the .html extension.

_python

This directory contains Python hooks for the template engine.

Project-wide reference ids

Urubu has the concept of project-wide reference ids. You can use them to refer to link objects in your content and configuration. Their definition comes from two sources:

  • global reference ids are mapped to link objects in the _site.yml configuration file, as discussed earlier.
  • all content pages and folders objects have reference ids.

Project-wide references ids live in a single namespace. For pages and folders, the id is a root-relative pathname starting with a slash / and without file extension. By convention, global reference ids should not start with a /.

In your content and configuration info, you can also use relative reference ids. Urubu will resolve them depending on the file location in the project. In case of a name clash with a global reference id, you will have to disambiguate by adding pathname components.

In accordance with Markdown conventions, reference ids are case-insensitive.

Content files

Content files are Markdown files with extension .md. They should start with YAML front matter that defines a number of attributes, as in the following example:

---
title: Read me first
layout: page
date: 2014-01-15
---
<Markdown content>

The following attributes are predefined:

Attribute Description
title Specifies the page title. Mandatory.
layout Specifies the layout, without the .html extension, or null. Mandatory.
date Specifies the date in YYYY-MM-DD format. Optional.
tags A tag or list of tags for the content.
saveas Allows overriding of the output filename.

The layout attribute is mandatory, but can be given a null value. This is useful when the page content is used by other pages, but no html output is required for the page itself.

In addition, you can add arbitrary user-defined attributes. All attributes are made available as page object attributes to the template engine.

Markdown in attributes

Optionally, you can use markdown format in front matter attributes. Markdown processing is enabled by adding a .md suffix to the attribute. The resulting html code will be stored in a synthesized attribute without the .md suffix.

For example:

---
title:
layout: page
summary.md: |
    A summary of the page items as a list:

    * item 1
    * item 2
    * item 3
---

After processing, the page object will have a summary attribute with the html code.

Index files

Index files with basename index.md are a special kind of content files. They are used to specify the attributes and the content of a directory. There are two options to specify the content, explicitly with the content attribute or implicitly using the order attribute.

Attribute Description
content Defines the content explicitly as a list of reference ids or local link objects.
order Defines the attribute by which the content in the directory should be ordered.
reverse Optional boolean attribute defines reverse order or not. Default is false.

content and order are mutually exclusive; you should use one of the two options.

A local link object is a mapping with either a url key to an url, or a ref key to a reference id as mandatory items. In addtion, you can specify a title with a title key.

The ordering attribute can be predefined or user-defined, but it should be specified in each content file in the directory. As an example, you can specify that the content of a directory should be ordered as blog by the following front matter in the index file:

---
title: Blog
layout: blog_index
order: date
reverse: true
---

Tag directory

The optional top-level directory called tag has a predefined meaning. Urubu uses the corresponding folder in the build to hold the tag-related content view that it generates automatically. You can use the index file to set attributes such as the layout. However, the content will be generated by Urubu automatically and needs not be set.

================================================ FILE: doc/_build/manual/templates.html ================================================ Templates

Overview

Templates define the html layout for a particular page type. In a template you can mix plain html with control structures and variable interpolation. The html page is generated by evaluating the template with the appropriate evaluation context, provided by Urubu.

Templates are part of the website project setup. If you are a content contributor, you may not have to worry about them. All you have to do is specify the appropriate layout name in the YAML front matter of your content files.

In general, it is better to do programming in Python code. However, for the purpose of generation of pages in a format such as html, this is not very practical. Therefore, a template contains both html and programming constructs. Template programming is good for common tasks like the following:

  • iteration over a list of items
  • testing whether an item is defined
  • filtering items, possibly with user-defined filters
  • comparing the loop item object with the current object, to check whether it is active

Urubu interacts with templates by providing an evaluation context with the appropriate objects. The goal is to make the job of the templates as easy as possible with ready-to-use object attributes.

The template library

Urubu uses the Jinja2 templating language library.

Jinja2 has great documentation and you should check it out when using templates in Urubu.

A great feature of Jinja2 is template inheritance. With this technique, you can easily generate small variations of a parent template.

Description

Link objects are the primary objects that you use in templates. They come in a number of flavours:

Link object Description
global link object Defined in the _site.yml file.
local link object Defined locally in the content attribute of an index file.
folder object Corresponds to a project subdirectory.
page object Corresponds to a Markdown content file.
tag folder object Dedicated folder for content ordered by tag.
tag object Represents content corresponding to a specific tag.

Attributes

Link objects have attributes. The defined attributes depend on the type of the link object.

The following attributes are common to all link objects:

Attribute Description
url The url of the object.
title The title of the object.

All link objects except local link objects also have an id attribute:

Attribute Description
id The unique id by which the object is known in the project.

Folder and page objects have the following attributes:

Attribute Description
fn The pathname of the file or directory corresponding the object.
components The components of the object's pathname, without file extension, as a list.
mdate Modification date

Folder objects also have a content attribute:

Attribute Description
content The content of the folder as a list of page & folder objects.

In addition, all attributes specified in the YAML front matter of the corresponding index file will be available as attributes of the folder object.

Page objects have the following additional attributes:

Attribute Description
layout The template to render the object as a html file.
body The page content in html.
toc The table of contents of the page as an unordered html list.
breadcrumbs Breadcrumbs as a list. The current page object is at position 0, the containing folder objects are at the higher positions.
prev The previous page object in the content, or None if there is none
next The next page object in the content, or None if there is none

In addition, all attributes specified in the YAML front matter of the corresponding content file are available as attributes of the page object.

Index pages

Index pages are associated with index.md files. They are special in the sense that they define the attributes and the content of a folder. Therefore, they have the same content attribute as the corresponding folder object.

Tag objects

Tag objects are inferred by Urubu automatically. They list the content corresponding to a tag.

Attribute Description
id /tag/{{tag}}
components [tag, {{tag}}]
title tag
tag tag
layout tag
content List of page & folder objects corresponding to tag.

The tag content is ordered by date, most recent first. If the date is not defined, the modification date is used as a fallback (mdate attribute).

The layout name is predefined to tag. You have to provide the tag.html template to trigger the rendering of tag objects. In the simplest case, it may be sufficient to inherit from a general index layout.

Tag folder object

The tag folder object is a special top-level folder whose id is /tag. Urubu infers tag-related content for this folder automatically.

You can optionally create the corresponding directory in the source code, and use the index file to set attributes such as the layout. In any case, Urubu will create the object if tags are used, and infer the content attribute.

Attribute Description
id /tag
components [tag]
content A list of tag objects, inferred by Urubu.

The content is ordered according to the content size of tag objects, the largest one first.

Context variables

Urubu makes the context available to templates with two context variables.

site

This variable holds site-wide information.

It has one predefined attribute:

Attribute Description
reflinks A mapping from all reference ids to link objects.

Note that the id of the root object is /. Starting from there, you can traverse the whole site.

In addition, all the attributes specified in the _site.yml file will be available as attributes of the site variable.

this

This variable holds the current page or tag object.

================================================ FILE: doc/_build/manual/templating-in-pages.html ================================================ Templating constructs in pages

Overview

Writing in Markdown is great, but sometimes you run into limitations. For those cases, Urubu supports a feature gratefully borrowed from Jekyll: using templating constructs in content pages.

Basically, all content pages are processed by the templating engine before going to the Markdown processor. The full power of Jinja2 is thus available in your content pages.

The usage of templating constructs in content pages is best explained with examples. Therefore, we will start with some examples, and review the concepts afterwards.

Example usage

Task list icons

Suppose you want to emulate GitHub style task lists, as follows:

  • Task 1
  • Task 2
  • Task 1

An icon is used to show whether a task is still open or not.

We can support this by defining well-named reusable variables in a dedicated template file, as follows:

{% set open = '<i class="fa fa-square-o"></i>' %}
{% set done = '<i class="fa fa-check-square-o"></i>' %}

Variables open and done now hold HTML code that refers to icons. In these examples, I use the Font Awesome icon library. You will need to add the appropriate reference to the icon stylesheet in your base template.

Suppose these variables are defined in the file _layouts/util.html. We can import them in any content page as follows:

{% from 'util.html' import open, done %}

Note that Urubu knows to look up util.html in the _layouts/ directory, because that is where templates should be located.

Within the content page, we can use the variables as follows, to get the result as above:

* {{ open }} Task 1
* {{ done }} Task 2
* {{ open }} Task 1

General icon interface

Suppose you want a more general interface to icons, so that you can easily refer to any icon by name. This can be done with a Jinja2 macro. A macro is like a function that can take parameters:

{% macro fa(name, class='') %}
<i class="fa fa-{{name}} {{class}}"></i>
{% endmacro %}

Again, we can import the macro fa in content pages:

{% from 'util.html' import fa %}

Then we can use it as follows, for example to refer to the Github icon:

{{ fa('github') }}

This gives the following result:

We can pass additional CSS classes via the optional class parameter. The following example gets the alternative Github icon in twice the basic size:

{{ fa('github-alt', 'fa-2x') }}

This gives the following result:

Figure

Standard Markdown does not support the HTML5 <figure> tag, and the related <figcaption> tag to add captions. We can support this with the following macro:

{% macro figure(fn, caption='') %}
<figure>
  <img src="/img/{{fn}}" class="img-responsive" alt="{{caption}}">
  {% if caption %}
  <figcaption class="text-center">{{caption}}</figcaption>
  {% endif %}
</figure>
{% endmacro %}

This macro assumes that images will be placed in an img/ directory. In addition, it makes the image responsive using a Bootstrap class, and centers the optional caption. Again, we can use the macro by importing:

{% from 'util.html' import figure %}

This is an example usage:

{{ figure('urubu.jpg', "An Urubu - a brazilian vulture") }}

This gives the following result:

An Urubu - a brazilian vulture
An Urubu - a brazilian vulture

Templating concepts

Template processing is done first

The examples illustrate how you can use template variables and macros to construct HTML code. However, it is important to understand that template processing is done first, before Markdown processing (for good reasons). Thus, the HTML code from variables and macros first becomes part of Markdown source code. This works well because Markdown is designed to handle HTML transparently.

Full template power available

The examples demonstrate the use of variables, macros, and imports. This is merely the beginning: in fact, the full power of Jinja2 templates is available. This is a vast subject. To learn what is possible, see the Jinja2 Template Designer Documentation.

Context variables

When Urubu invokes template processing on a page, it automatically passes certain context variables. This works exactly like for regular templates, as described in Context Variables. Basically, variable this provides access to the page attributes, and variable site provides access to the global site attributes.

Template delimiters

Template support introduces new delimiters as follows:

  • {# ... #} for comments not included in the output
  • {{ ... }} for expressions, to print to the output
  • {% ... %} for statements

These delimiters deserve some attention.

First, the comment delimiters are interesting because they add a functionality that is not available in Markdown: comments that will not show up in the output.

Secondly, as always with delimiters, there is the problem of how to escape them if you want to use them literally in source code, without interpretation.

For an inline literal or snippet you can use literal expressions. For example, to get {{ you can write {{ '{{' }} .

For a larger section, you can mark a block raw. For example, to get the list shown earlier in this section, you can write:

{% raw %}
* `{# ... #}` for comments not included in the output
* `{{ ... }}` for expressions, to print to the output
* `{% ... %}` for statements
{% endraw %}
================================================ FILE: doc/_build/more/about.html ================================================ About this site

Author

The Urubu software is written by Jan Decaluwe.

License

The Urubu software is licensed under the GNU Affero General Public License.

The content on this documentation website is licensed under the CC-BY-SA License.

Development

The Urubu software is developed on GitHub in the Urubu repo.

The documentation is developed as a website in a gh-pages branch in the same repo. It can be accessed from the custom domain urubu.jandecaluwe.com but it is hosted on GitHub Pages.

Theme

The theme on this website uses the Bootstrap framework, and is based on stock Bootstrap.

Trivia

An urubu is a brazilian vulture. Urubu is also the 10th album of Antonio Carlos Jobim, one of my favorite song composers.

================================================ FILE: doc/_build/more/index.html ================================================ More

More

================================================ FILE: doc/_build/more/sites.html ================================================ Websites powered by Urubu

I created Urubu to solve a personal problem: how to create and maintain websites for my projects. I open-sourced it "in the hope it can be useful". On this page I list a number of websites that are powered by Urubu.

By others

Sigasi Insights - Documentation for Sigasi's tools.

Leonardo Uieda - Website about Leonardo's professional activities.

PINGA lab - Site for the PINGA lab, a research group studying inverse problems in geophysics.

For others, by me

Vlaamse sofrologen - Site of the flemish sophrologists (in Dutch)

Troca Vins Naturels - Natural wines

MyHDL

MyHDL website - all about MyHDL, for users

MyHDL development website - info for MyHDL developers

Urubu

Urubu Quickstart - the Quickstart companion site for Urubu

Urubu Documentation - this site

Personal

Jan Decaluwe My site about professional activities

Jan Decaluwe / Music My music projects

Jan Decaluwe / Opinions My opinions, in Dutch

================================================ FILE: doc/_build/news/2014-01-12.html ================================================ Urubu 0.1 released

Introducing Urubu, a Python-based micro CMS for static websites. Read about the rationale behind it.

================================================ FILE: doc/_build/news/2014-01-22.html ================================================ Urubu 0.2 released

This release adds support for github-style task lists.

================================================ FILE: doc/_build/news/2014-02-15.html ================================================ Urubu 0.2.1 released

This is a bug fix release.

================================================ FILE: doc/_build/news/2014-02-27.html ================================================ Urubu 0.3 released

This release adds markdown support for front-matter attributes. Read more »

================================================ FILE: doc/_build/news/2014-03-18.html ================================================ Urubu 0.3.1 released

This is a bug-fix release.

================================================ FILE: doc/_build/news/2014-05-25.html ================================================ Urubu 0.4 and Urubu Quickstart released

Release features:

================================================ FILE: doc/_build/news/2014-09-08.html ================================================ Urubu 0.5 released

Urubu 0.5 introduces tag support.

Read my blog post for an introduction.

================================================ FILE: doc/_build/news/2015-01-28.html ================================================ Urubu 0.6 released

Urubu 0.6 improves on wiki links: now you can link to a location within a page.

Read my blog post for more info.

================================================ FILE: doc/_build/news/2015-03-07.html ================================================ Urubu 0.7: Python 3 support, baseurl option

Urubu 0.7 adds features that make it more flexible to use.

First, the release adds Python 3 support, from a single codebase. You can use Python 2.7 or Python 3.4.

Second, there is now a baseurl option to add a prefix to generated local URLs. More info ».

On the other hand, the checklist extension has been removed as it caused issues with reference id resolution.

================================================ FILE: doc/_build/news/2015-11-22.html ================================================ Urubu 0.8 released

Release highlights:

  • the urubu serve command automatically takes the baseurl option into account (Pull request #27).

  • when an undefined anchor is referred to in a page, a warning is generated, just like for references to undefined pages (Issue #30).

  • the layout attribute can be assigned null. In this way the page content can be used by other pages, but no html is generated for the page itself.

In addition, a significant effort was put into development robustness. In particular, a regression test suite has been added. This is based on py.test and tox, so that both Python 2.7 and 3.4 are verified.

================================================ FILE: doc/_build/news/2015-12-15.html ================================================ Urubu 0.9.0 released

This release adds support for Tipue Search, an open source search solution based on Javascript in the browser.

Read more in the chapter Adding Search in the manual.

================================================ FILE: doc/_build/news/2016-01-01.html ================================================ Urubu 1.0.0 released

This release adds support for the process_info Python hook. This hook provides a powerful way to assist in templating. Basically, it provides full Python power to inspect, verify, modify, and add page attributes. For example, you can use it to define a default layout, or a specific layout for pages in a certain directory.

Read more in the manual: The process_info hook.

There is also a new keep_files configuration attribute, that lets you preserve files that would otherwise be ignored. See the documentation.

================================================ FILE: doc/_build/news/2016-01-10.html ================================================ Urubu 1.1.0 released

This release adds experimental support for the <mark> tag.

Read more in the manual: Support for the mark tag and in this blog post.

================================================ FILE: doc/_build/news/2016-02-12.html ================================================ Urubu 1.2.0 released

The highlight of this release is support for Templating constructs in pages.

================================================ FILE: doc/_build/news/2016-11-14.html ================================================ Urubu 1.3.0 released

Highlights:

  • Add posibility to override output filename. (#51). See the saveas attribute in the manual. An example usage, see How do I make a sitemap?.

  • The urubu serve command is more secure. This is transparent to the user (#49).

  • Added option for jinja2 to fail on undefined vars (#47). See the strict_undefined attribute in the manual.

================================================ FILE: doc/_build/news/2018-08-15.html ================================================ Urubu 1.3.1 released

Maintenance release: bug fixes and small enhancements to existing features. See the git log and the manual.

================================================ FILE: doc/_build/news/2024-12-30.html ================================================ Urubu 1.4.0 released

Python3 only.

================================================ FILE: doc/_build/news/2026-03-30.html ================================================ Urubu 1.4.1 released

Maintenance release: added test dependencies to setup.py, removed Python 2 compatibility layer, and relaxed the Markdown version pin to >= 3.0.

================================================ FILE: doc/_build/news/index.html ================================================ Newsfeed

30-Mar-2026  Urubu 1.4.1 released

Maintenance release: added test dependencies to setup.py, removed Python 2 compatibility layer, and relaxed the Markdown version pin to >= 3.0.


30-Dec-2024  Urubu 1.4.0 released

Python3 only.


15-Aug-2018  Urubu 1.3.1 released

Maintenance release: bug fixes and small enhancements to existing features. See the git log and the manual.


14-Nov-2016  Urubu 1.3.0 released

Highlights:

  • Add posibility to override output filename. (#51). See the saveas attribute in the manual. An example usage, see How do I make a sitemap?.

  • The urubu serve command is more secure. This is transparent to the user (#49).

  • Added option for jinja2 to fail on undefined vars (#47). See the strict_undefined attribute in the manual.


12-Feb-2016  Urubu 1.2.0 released

The highlight of this release is support for Templating constructs in pages.


10-Jan-2016  Urubu 1.1.0 released

This release adds experimental support for the <mark> tag.

Read more in the manual: Support for the mark tag and in this blog post.


01-Jan-2016  Urubu 1.0.0 released

This release adds support for the process_info Python hook. This hook provides a powerful way to assist in templating. Basically, it provides full Python power to inspect, verify, modify, and add page attributes. For example, you can use it to define a default layout, or a specific layout for pages in a certain directory.

Read more in the manual: The process_info hook.

There is also a new keep_files configuration attribute, that lets you preserve files that would otherwise be ignored. See the documentation.


15-Dec-2015  Urubu 0.9.0 released

This release adds support for Tipue Search, an open source search solution based on Javascript in the browser.

Read more in the chapter Adding Search in the manual.


22-Nov-2015  Urubu 0.8 released

Release highlights:

  • the urubu serve command automatically takes the baseurl option into account (Pull request #27).

  • when an undefined anchor is referred to in a page, a warning is generated, just like for references to undefined pages (Issue #30).

  • the layout attribute can be assigned null. In this way the page content can be used by other pages, but no html is generated for the page itself.

In addition, a significant effort was put into development robustness. In particular, a regression test suite has been added. This is based on py.test and tox, so that both Python 2.7 and 3.4 are verified.


07-Mar-2015  Urubu 0.7: Python 3 support, baseurl option

Urubu 0.7 adds features that make it more flexible to use.

First, the release adds Python 3 support, from a single codebase. You can use Python 2.7 or Python 3.4.

Second, there is now a baseurl option to add a prefix to generated local URLs. More info ».

On the other hand, the checklist extension has been removed as it caused issues with reference id resolution.


28-Jan-2015  Urubu 0.6 released

Urubu 0.6 improves on wiki links: now you can link to a location within a page.

Read my blog post for more info.


08-Sep-2014  Urubu 0.5 released

Urubu 0.5 introduces tag support.

Read my blog post for an introduction.


25-May-2014  Urubu 0.4 and Urubu Quickstart released

Release features:


18-Mar-2014  Urubu 0.3.1 released

This is a bug-fix release.


27-Feb-2014  Urubu 0.3 released

This release adds markdown support for front-matter attributes. Read more »


15-Feb-2014  Urubu 0.2.1 released

This is a bug fix release.


22-Jan-2014  Urubu 0.2 released

This release adds support for github-style task lists.


12-Jan-2014  Urubu 0.1 released

Introducing Urubu, a Python-based micro CMS for static websites. Read about the rationale behind it.


================================================ FILE: doc/_build/search.html ================================================ Search results
================================================ FILE: doc/_build/start.html ================================================ Overview

What is Urubu?

Urubu is a tool to build static websites. The following sections will help you to decide whether it is the right tool for you.

Static versus dynamic

A static website is the simple case. It consists of a set of fixed pages. The only job of the web server is to serve the page that you request.

The opposite is a dynamic website. In this case, you interact with a program on the web server. Depending on the request, the web server program generates a response page on the fly.

Clearly, a dynamic website supports a much more interactive and sophisticated web experience. If this is what you need, you should consider a full-fledged CMS or CMS generator tool. There is a wide choice of them in the Python world.

On the other hand, a static website is great for performance, security and maintainability. If you don't need the overhead of a dynamic CMS, it is a wise choice.

Why a tool?

One option is to write a static website by hand by editing the html code for each page. However, this quickly becomes an unpractical solution for two reasons.

First, writing html is no fun. The markup overhead is error prone and makes it difficult to read the actual content. In Urubu, you use Markdown for authoring instead. Markdown is an almost zero overhead input format and feels like a natural way to write content in plain text.

Secondly, html pages have a lot of non-content overhead that is equal or similar across pages, such as navigation info. Duplicating and maintaining this info manually is error prone and time consuming. In Urubu, you use templates (also known as layouts) instead. They make it easy to define the common html structure of a set of similar pages.

Why Urubu?

There is no shortage of static web site generators, including a lot of Python solutions. However, these tools are typically blog oriented. If your website is primarily a blog, with content in reverse chronological order and with good support for tagging and archiving, there are many other solutions than Urubu.

On the other hand, if you view your website as a set of logically connected content pages, Urubu is an excellent choice. Urubu makes it it easy to define a good navigation structure, so that a user is never "lost". This is especially important for technical content.

Of course, you can also include a blog in an Urubu site. Within a folder, you can specify how the content should be ordered using an arbitrary key. For a blog, this would be reverse order by date.

Urubu's ideal use case

If you would like to develop a website like a software project, you will feel at home with Urubu. For example, you can maintain an Urubu site in a git or mercurial repository and use the workflows that these systems enable. For example, you can collaborate on GitHub or Bitbucket through pull requests. Also, deployment can be as straightforward as pushing to an upstream repository.

================================================ FILE: doc/_build/tipuesearch/tipuesearch.css ================================================ /* Tipue Search 5.0 Copyright (c) 2015 Tipue Tipue Search is released under the MIT License http://www.tipue.com/search */ /* #tipue_search_input { font: 13px/1.6 'open sans', sans-serif; color: #333; padding: 12px 12px 12px 40px; width: 170px; border: 1px solid #e2e2e2; border-radius: 0; -moz-appearance: none; -webkit-appearance: none; box-shadow: none; outline: 0; margin: 0; background: #fff url('img/search.png') no-repeat 15px 15px; } */ #tipue_search_content { max-width: 650px; padding-top: 15px; margin: 0; } #tipue_search_warning { font: 300 15px/1.6 'Open Sans', sans-serif; color: #555; margin: 7px 0; } #tipue_search_warning a { color: #396; text-decoration: none; } #tipue_search_warning a:hover { color: #555; } #tipue_search_results_count { font: 300 15px/1.7 'Open Sans', sans-serif; color: #555; } .tipue_search_content_title { font: 300 21px/1.7 'Open Sans', sans-serif; margin-top: 23px; } .tipue_search_content_title a { color: #333; text-decoration: none; } .tipue_search_content_title a:hover { color: #555; } .tipue_search_content_url { font: 300 14px/1.9 'Open Sans', sans-serif; word-wrap: break-word; hyphens: auto; } .tipue_search_content_url a { color: #396; text-decoration: none; } .tipue_search_content_url a:hover { color: #555; } .tipue_search_content_text { font: 300 15px/1.6 'Open Sans', sans-serif; color: #555; word-wrap: break-word; hyphens: auto; margin-top: 3px; } .tipue_search_content_debug { font: 300 13px/1.6 'Open Sans', sans-serif; color: #555; margin: 5px 0; } .h01 { color: #333; font-weight: 400; } #tipue_search_foot { margin: 51px 0 21px 0; } #tipue_search_foot_boxes { padding: 0; margin: 0; font: 12px 'Open Sans', sans-serif; } #tipue_search_foot_boxes li { list-style: none; margin: 0; padding: 0; display: inline; } #tipue_search_foot_boxes li a { padding: 10px 17px 11px 17px; background-color: #fff; border: 1px solid #e2e2e2; border-radius: 1px; color: #333; margin-right: 7px; text-decoration: none; text-align: center; } #tipue_search_foot_boxes li.current { padding: 10px 17px 11px 17px; background: #f6f6f6; border: 1px solid #e2e2e2; border-radius: 1px; color: #333; margin-right: 7px; text-align: center; } #tipue_search_foot_boxes li a:hover { background: #f6f6f6; } /* spinner */ .tipue_search_spinner { padding: 31px 0; width: 50px; height: 28px; } .tipue_search_spinner > div { background-color: #777; height: 100%; width: 3px; display: inline-block; margin-right: 2px; -webkit-animation: stretchdelay 1.2s infinite ease-in-out; animation: stretchdelay 1.2s infinite ease-in-out; } .tipue_search_spinner .tipue_search_rect2 { -webkit-animation-delay: -1.1s; animation-delay: -1.1s; } .tipue_search_spinner .tipue_search_rect3 { -webkit-animation-delay: -1.0s; animation-delay: -1.0s; } @-webkit-keyframes stretchdelay { 0%, 40%, 100% { -webkit-transform: scaleY(0.4) } 20% { -webkit-transform: scaleY(1.0) } } @keyframes stretchdelay { 0%, 40%, 100% { transform: scaleY(0.4); -webkit-transform: scaleY(0.4); } 20% { transform: scaleY(1.0); -webkit-transform: scaleY(1.0); } } ================================================ FILE: doc/_build/tipuesearch/tipuesearch.css.in ================================================ /* Tipue Search 5.0 Copyright (c) 2015 Tipue Tipue Search is released under the MIT License http://www.tipue.com/search */ #tipue_search_input { font: 13px/1.6 'open sans', sans-serif; color: #333; padding: 12px 12px 12px 40px; width: 170px; border: 1px solid #e2e2e2; border-radius: 0; -moz-appearance: none; -webkit-appearance: none; box-shadow: none; outline: 0; margin: 0; background: #fff url('img/search.png') no-repeat 15px 15px; } #tipue_search_content { max-width: 650px; padding-top: 15px; margin: 0; } #tipue_search_warning { font: 300 15px/1.6 'Open Sans', sans-serif; color: #555; margin: 7px 0; } #tipue_search_warning a { color: #396; text-decoration: none; } #tipue_search_warning a:hover { color: #555; } #tipue_search_results_count { font: 300 15px/1.7 'Open Sans', sans-serif; color: #555; } .tipue_search_content_title { font: 300 21px/1.7 'Open Sans', sans-serif; margin-top: 23px; } .tipue_search_content_title a { color: #333; text-decoration: none; } .tipue_search_content_title a:hover { color: #555; } .tipue_search_content_url { font: 300 14px/1.9 'Open Sans', sans-serif; word-wrap: break-word; hyphens: auto; } .tipue_search_content_url a { color: #396; text-decoration: none; } .tipue_search_content_url a:hover { color: #555; } .tipue_search_content_text { font: 300 15px/1.6 'Open Sans', sans-serif; color: #555; word-wrap: break-word; hyphens: auto; margin-top: 3px; } .tipue_search_content_debug { font: 300 13px/1.6 'Open Sans', sans-serif; color: #555; margin: 5px 0; } .h01 { color: #333; font-weight: 400; } #tipue_search_foot { margin: 51px 0 21px 0; } #tipue_search_foot_boxes { padding: 0; margin: 0; font: 12px 'Open Sans', sans-serif; } #tipue_search_foot_boxes li { list-style: none; margin: 0; padding: 0; display: inline; } #tipue_search_foot_boxes li a { padding: 10px 17px 11px 17px; background-color: #fff; border: 1px solid #e2e2e2; border-radius: 1px; color: #333; margin-right: 7px; text-decoration: none; text-align: center; } #tipue_search_foot_boxes li.current { padding: 10px 17px 11px 17px; background: #f6f6f6; border: 1px solid #e2e2e2; border-radius: 1px; color: #333; margin-right: 7px; text-align: center; } #tipue_search_foot_boxes li a:hover { background: #f6f6f6; } /* spinner */ .tipue_search_spinner { padding: 31px 0; width: 50px; height: 28px; } .tipue_search_spinner > div { background-color: #777; height: 100%; width: 3px; display: inline-block; margin-right: 2px; -webkit-animation: stretchdelay 1.2s infinite ease-in-out; animation: stretchdelay 1.2s infinite ease-in-out; } .tipue_search_spinner .tipue_search_rect2 { -webkit-animation-delay: -1.1s; animation-delay: -1.1s; } .tipue_search_spinner .tipue_search_rect3 { -webkit-animation-delay: -1.0s; animation-delay: -1.0s; } @-webkit-keyframes stretchdelay { 0%, 40%, 100% { -webkit-transform: scaleY(0.4) } 20% { -webkit-transform: scaleY(1.0) } } @keyframes stretchdelay { 0%, 40%, 100% { transform: scaleY(0.4); -webkit-transform: scaleY(0.4); } 20% { transform: scaleY(1.0); -webkit-transform: scaleY(1.0); } } ================================================ FILE: doc/_build/tipuesearch/tipuesearch.js ================================================ /* Tipue Search 5.0 Copyright (c) 2015 Tipue Tipue Search is released under the MIT License http://www.tipue.com/search */ (function($) { $.fn.tipuesearch = function(options) { var set = $.extend( { 'show' : 7, 'newWindow' : false, 'showURL' : true, 'showTitleCount' : true, 'minimumLength' : 3, 'descriptiveWords' : 25, 'highlightTerms' : true, 'highlightEveryTerm' : false, 'mode' : 'static', 'liveDescription' : '*', 'liveContent' : '*', 'contentLocation' : 'tipuesearch/tipuesearch_content.json', 'debug' : false }, options); return this.each(function() { var tipuesearch_in = { pages: [] }; $.ajaxSetup({ async: false }); var tipuesearch_t_c = 0; if (set.mode == 'live') { for (var i = 0; i < tipuesearch_pages.length; i++) { $.get(tipuesearch_pages[i]) .done(function(html) { var cont = $(set.liveContent, html).text(); cont = cont.replace(/\s+/g, ' '); var desc = $(set.liveDescription, html).text(); desc = desc.replace(/\s+/g, ' '); var t_1 = html.toLowerCase().indexOf(''); var t_2 = html.toLowerCase().indexOf('', t_1 + 7); if (t_1 != -1 && t_2 != -1) { var tit = html.slice(t_1 + 7, t_2); } else { var tit = tipuesearch_string_1; } tipuesearch_in.pages.push( { "title": tit, "text": desc, "tags": cont, "url": tipuesearch_pages[i] }); }); } } if (set.mode == 'json') { $.getJSON(set.contentLocation) .done(function(json) { tipuesearch_in = $.extend({}, json); }); } if (set.mode == 'static') { tipuesearch_in = $.extend({}, tipuesearch); } var tipue_search_w = ''; if (set.newWindow) { tipue_search_w = ' target="_blank"'; } function getURLP(name) { return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search)||[,""])[1].replace(/\+/g, '%20')) || null; } if (getURLP('q')) { $('#tipue_search_input').val(getURLP('q')); getTipueSearch(0, true); } $(this).keyup(function(event) { if(event.keyCode == '13') { getTipueSearch(0, true); } }); function getTipueSearch(start, replace) { $('#tipue_search_content').hide(); $('#tipue_search_content').html('
'); $('#tipue_search_content').show(); var out = ''; var results = ''; var show_replace = false; var show_stop = false; var standard = true; var c = 0; found = []; var d = $('#tipue_search_input').val().toLowerCase(); d = $.trim(d); if ((d.match("^\"") && d.match("\"$")) || (d.match("^'") && d.match("'$"))) { standard = false; } if (standard) { var d_w = d.split(' '); d = ''; for (var i = 0; i < d_w.length; i++) { var a_w = true; for (var f = 0; f < tipuesearch_stop_words.length; f++) { if (d_w[i] == tipuesearch_stop_words[f]) { a_w = false; show_stop = true; } } if (a_w) { d = d + ' ' + d_w[i]; } } d = $.trim(d); d_w = d.split(' '); } else { d = d.substring(1, d.length - 1); } if (d.length >= set.minimumLength) { if (standard) { if (replace) { var d_r = d; for (var i = 0; i < d_w.length; i++) { for (var f = 0; f < tipuesearch_replace.words.length; f++) { if (d_w[i] == tipuesearch_replace.words[f].word) { d = d.replace(d_w[i], tipuesearch_replace.words[f].replace_with); show_replace = true; } } } d_w = d.split(' '); } var d_t = d; for (var i = 0; i < d_w.length; i++) { for (var f = 0; f < tipuesearch_stem.words.length; f++) { if (d_w[i] == tipuesearch_stem.words[f].word) { d_t = d_t + ' ' + tipuesearch_stem.words[f].stem; } } } d_w = d_t.split(' '); for (var i = 0; i < tipuesearch_in.pages.length; i++) { var score = 0; var s_t = tipuesearch_in.pages[i].text; for (var f = 0; f < d_w.length; f++) { var pat = new RegExp(d_w[f], 'gi'); if (tipuesearch_in.pages[i].title.search(pat) != -1) { var m_c = tipuesearch_in.pages[i].title.match(pat).length; score += (20 * m_c); } if (tipuesearch_in.pages[i].text.search(pat) != -1) { var m_c = tipuesearch_in.pages[i].text.match(pat).length; score += (20 * m_c); } if (set.highlightTerms) { if (set.highlightEveryTerm) { var patr = new RegExp('(' + d_w[f] + ')', 'gi'); } else { var patr = new RegExp('(' + d_w[f] + ')', 'i'); } s_t = s_t.replace(patr, "$1"); } if (tipuesearch_in.pages[i].tags.search(pat) != -1) { var m_c = tipuesearch_in.pages[i].tags.match(pat).length; score += (10 * m_c); } if (tipuesearch_in.pages[i].url.search(pat) != -1) { score += 20; } if (score != 0) { for (var e = 0; e < tipuesearch_weight.weight.length; e++) { if (tipuesearch_in.pages[i].url == tipuesearch_weight.weight[e].url) { score += tipuesearch_weight.weight[e].score; } } } if (d_w[f].match('^-')) { pat = new RegExp(d_w[f].substring(1), 'i'); if (tipuesearch_in.pages[i].title.search(pat) != -1 || tipuesearch_in.pages[i].text.search(pat) != -1 || tipuesearch_in.pages[i].tags.search(pat) != -1) { score = 0; } } } if (score != 0) { found.push( { "score": score, "title": tipuesearch_in.pages[i].title, "desc": s_t, "url": tipuesearch_in.pages[i].url }); c++; } } } else { for (var i = 0; i < tipuesearch_in.pages.length; i++) { var score = 0; var s_t = tipuesearch_in.pages[i].text; var pat = new RegExp(d, 'gi'); if (tipuesearch_in.pages[i].title.search(pat) != -1) { var m_c = tipuesearch_in.pages[i].title.match(pat).length; score += (20 * m_c); } if (tipuesearch_in.pages[i].text.search(pat) != -1) { var m_c = tipuesearch_in.pages[i].text.match(pat).length; score += (20 * m_c); } if (set.highlightTerms) { if (set.highlightEveryTerm) { var patr = new RegExp('(' + d + ')', 'gi'); } else { var patr = new RegExp('(' + d + ')', 'i'); } s_t = s_t.replace(patr, "$1"); } if (tipuesearch_in.pages[i].tags.search(pat) != -1) { var m_c = tipuesearch_in.pages[i].tags.match(pat).length; score += (10 * m_c); } if (tipuesearch_in.pages[i].url.search(pat) != -1) { score += 20; } if (score != 0) { for (var e = 0; e < tipuesearch_weight.weight.length; e++) { if (tipuesearch_in.pages[i].url == tipuesearch_weight.weight[e].url) { score += tipuesearch_weight.weight[e].score; } } } if (score != 0) { found.push( { "score": score, "title": tipuesearch_in.pages[i].title, "desc": s_t, "url": tipuesearch_in.pages[i].url }); c++; } } } if (c != 0) { if (set.showTitleCount && tipuesearch_t_c == 0) { var title = document.title; document.title = '(' + c + ') ' + title; tipuesearch_t_c++; } if (show_replace == 1) { out += '
' + tipuesearch_string_2 + ' ' + d + '. ' + tipuesearch_string_3 + ' ' + d_r + '
'; } if (c == 1) { out += '
' + tipuesearch_string_4 + '
'; } else { c_c = c.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); out += '
' + c_c + ' ' + tipuesearch_string_5 + '
'; } found.sort(function(a, b) { return b.score - a.score } ); var l_o = 0; for (var i = 0; i < found.length; i++) { if (l_o >= start && l_o < set.show + start) { out += ''; if (set.debug) { out += '
Score: ' + found[i].score + '
'; } if (set.showURL) { var s_u = found[i].url.toLowerCase(); if(s_u.indexOf('http://') == 0) { s_u = s_u.slice(7); } out += ''; } if (found[i].desc) { var t = found[i].desc; var t_d = ''; var t_w = t.split(' '); if (t_w.length < set.descriptiveWords) { t_d = t; } else { for (var f = 0; f < set.descriptiveWords; f++) { t_d += t_w[f] + ' '; } } t_d = $.trim(t_d); if (t_d.charAt(t_d.length - 1) != '.') { t_d += ' ...'; } out += '
' + t_d + '
'; } } l_o++; } if (c > set.show) { var pages = Math.ceil(c / set.show); var page = (start / set.show); out += '
    '; if (start > 0) { out += '
  • ' + tipuesearch_string_6 + '
  • '; } if (page <= 2) { var p_b = pages; if (pages > 3) { p_b = 3; } for (var f = 0; f < p_b; f++) { if (f == page) { out += '
  • ' + (f + 1) + '
  • '; } else { out += '
  • ' + (f + 1) + '
  • '; } } } else { var p_b = page + 2; if (p_b > pages) { p_b = pages; } for (var f = page - 1; f < p_b; f++) { if (f == page) { out += '
  • ' + (f + 1) + '
  • '; } else { out += '
  • ' + (f + 1) + '
  • '; } } } if (page + 1 != pages) { out += '
  • ' + tipuesearch_string_7 + '
  • '; } out += '
'; } } else { out += '
' + tipuesearch_string_8 + '
'; } } else { if (show_stop) { out += '
' + tipuesearch_string_8 + '. ' + tipuesearch_string_9 + '
'; } else { out += '
' + tipuesearch_string_10 + '
'; if (set.minimumLength == 1) { out += '
' + tipuesearch_string_11 + '
'; } else { out += '
' + tipuesearch_string_12 + ' ' + set.minimumLength + ' ' + tipuesearch_string_13 + '
'; } } } $('#tipue_search_content').hide(); $('#tipue_search_content').html(out); $('#tipue_search_content').slideDown(200); $('#tipue_search_replaced').click(function() { getTipueSearch(0, false); }); $('.tipue_search_foot_box').click(function() { var id_v = $(this).attr('id'); var id_a = id_v.split('_'); getTipueSearch(parseInt(id_a[0]), id_a[1]); }); } }); }; })(jQuery); ================================================ FILE: doc/_build/tipuesearch/tipuesearch_content.js ================================================ var tipuesearch = {"pages": [ {"title": "Tipue", "text": "", "tags": "jQuery HTML5 CSS", "url": "http://www.tipue.com"}, {"title": "Tipue Search, a site search engine jQuery plugin", "text": "Tipue Search is a site search engine jQuery plugin. It's free, open source, responsive and fast. Tipue Search only needs a browser that supports jQuery. It doesn't need MySQL or similar. In Static mode it doesn't even need a web server.", "tags": "JavaScript", "url": "http://www.tipue.com/search"}, {"title": "Tipue Search Documentation", "text": "Tipue Search is a site search engine jQuery plugin. It's free, open source and responsive. Tipue Search uses various modes for loading content. Static mode uses a JavaScript object, while JSON mode uses JSON. Live mode grabs content from a list of pages dynamically.", "tags": "docs", "url": "http://www.tipue.com/search/docs"}, {"title": "Tipue Search Static mode demo", "text": "Tipue Search is a site search engine jQuery plugin. This is a demo of Static mode. Enter tipue into the search box above.", "tags": "", "url": "http://www.tipue.com/search/demos/static"}, {"title": "Tipue Search Live mode demo", "text": "Tipue Search is a site search engine jQuery plugin. This is a demo of Live mode. Enter tipue into the search box above.", "tags": "", "url": "http://www.tipue.com/search/demos/live"}, {"title": "Tipue jQuery plugins Support", "text": "If you're stuck we offer a range of flexible support plans for our jQuery plugins.", "tags": "", "url": "http://www.tipue.com/support"}, {"title": "Tipr, a small and simple jQuery tooltip plugin", "text": "Tipr is a small and simple jQuery tooltip plugin. It's free and open source. Tipr displays attractive tooltips, and it's a shade under 4KB, CSS included.", "tags": "JavaScript", "url": "http://www.tipue.com/tipr"}, {"title": "The Tipue blog", "text": "An occasional blog covering CSS, web development, etc.", "tags": "HTML5", "url": "http://www.tipue.com/?d=2"}, {"title": "About Tipue", "text": "Tipue is a small web development studio based in North London. We've been around for well over a decade. We design innovative add-ins, plugins, code and features with heavy-duty Perl, MySQL and jQuery.", "tags": "", "url": "http://www.tipue.com/about"}, {"title": "The Tipue blog - The complete guide to centering a div", "text": "Every new developer inevitably finds that centering a div isn't as obvious as you'd expect. Centering what's inside a div is easy enough by giving the text-align property a value of center, but then things tend to get a bit sticky. When you get to centering a div vertically, you can end up in a world of CSS hurt.", "tags": "HTML", "url": "http://www.tipue.com/blog/center-a-div"}, {"title": "The Tipue blog - Native HTML5 autocomplete with input list", "text": "This article shows how with the HTML5 input list attribute and datalist element you can easily set up an input box with a custom autocomplete without jQuery, JavaScript or similar.", "tags": "", "url": "http://www.tipue.com/blog/input-list"}, {"title": "The Tipue blog - The really simple guide to z-index", "text": "The CSS z-index property often trips up new and even experienced developers. The aim of this article is to boil down a somewhat-complex specification to 3 major points, which should ease most z-index pain.", "tags": "", "url": "http://www.tipue.com/z-index"} ]}; ================================================ FILE: doc/_build/tipuesearch/tipuesearch_content.json ================================================ { "pages": [ { "tags": "", "text": "", "title": "Search results", "url": "/search.html" }, { "tags": "", "text": "30-Mar-2026: Urubu 1.4.1 released For websites, not just blogs Set up a website as logically related content. Content\nordering is flexible , not just by date. Focus on navigation Easily set up a navbar, a table of contents sidebar,\nbreadcrumbs and pagers. Ready for Bootstrap Urubu plays well with Bootstrap , the popular framework\nfor great looking websites. Markdown content Enter content in light-weight Markdown syntax, with\npopular extensions. Wiki links Easily refer to other pages like\nin wikis , using Markdown syntax. Powerful templating Use the powerful Jinja2 templating library to \ndefine page layouts. Sophisticated control Per-page control of page layout \n and other stuff. Plus user-defined variables . Python power Urubu is built with Python. It provides Python hooks to assist in templating. Ideal with git Use a git workflow to develop\nyour website. Deploy by pushing. And of course, it's open source!", "title": "Urubu", "url": "/index.html" }, { "tags": "", "text": "What is Urubu? Urubu is a tool to build static websites . The following sections will help\nyou to decide whether it is the right tool for you. Static versus dynamic A static website is the simple case. It consists of a set of fixed pages. The\nonly job of the web server is to serve the page that you request. The opposite is a dynamic website. In this case, you interact with a program on\nthe web server. Depending on the request, the web server program generates a\nresponse page on the fly. Clearly, a dynamic website supports a much more interactive and sophisticated\nweb experience. If this is what you need, you should consider a full-fledged\nCMS or CMS generator tool. There is a wide choice of them in the Python\nworld. On the other hand, a static website is great for performance, security and\nmaintainability. If you don't need the overhead of a dynamic CMS, it is a\nwise choice. Why a tool? One option is to write a static website by hand by editing the html code for\neach page. However, this quickly becomes an unpractical solution for two\nreasons. First, writing html is no fun. The markup overhead is error prone and makes it\ndifficult to read the actual content. In Urubu, you use Markdown for\nauthoring instead. Markdown is an almost zero overhead input format and feels\nlike a natural way to write content in plain text. Secondly, html pages have a lot of non-content overhead that is equal or\nsimilar across pages, such as navigation info. Duplicating and maintaining this\ninfo manually is error prone and time consuming. In Urubu, you use templates\n(also known as layouts) instead. They make it easy to define the common html\nstructure of a set of similar pages. Why Urubu? There is no shortage of static web site generators, including a lot of Python\nsolutions . However, these tools are typically blog oriented. If\nyour website is primarily a blog, with content in reverse chronological order\nand with good support for tagging and archiving, there are many other solutions\nthan Urubu. On the other hand, if you view your website as a set of logically connected\ncontent pages, Urubu is an excellent choice . Urubu makes it it easy to define\na good navigation structure, so that a user is never \"lost\". This is especially\nimportant for technical content. Of course, you can also include a blog in an Urubu site. Within a folder, you\ncan specify how the content should be ordered using an arbitrary key. For a\nblog, this would be reverse order by date. Urubu's ideal use case If you would like to develop a website like a software project, you will feel\nat home with Urubu. For example, you can maintain an Urubu site in a git or\nmercurial repository and use the workflows that these systems enable. For\nexample, you can collaborate on GitHub or Bitbucket through pull\nrequests . Also, deployment can be as straightforward as pushing to an upstream\nrepository.", "title": "Overview", "url": "/start.html" }, { "tags": "", "text": "Urubu 0.5 introduces tag support. Read my blog post for an introduction.", "title": "Urubu 0.5 released", "url": "/news/2014-09-08.html" }, { "tags": "", "text": "This release adds markdown support for front-matter attributes. Read more »", "title": "Urubu 0.3 released", "url": "/news/2014-02-27.html" }, { "tags": "", "text": "Maintenance release: bug fixes and small enhancements to existing features.\nSee the git log and the manual.", "title": "Urubu 1.3.1 released", "url": "/news/2018-08-15.html" }, { "tags": "", "text": "This release adds support for Tipue Search, an open source search solution\nbased on Javascript in the browser. Read more in the chapter Adding Search in the manual.", "title": "Urubu 0.9.0 released", "url": "/news/2015-12-15.html" }, { "tags": "", "text": "Urubu 0.7 adds features that make it more flexible to use. First, the release adds Python 3 support, from a single codebase.\nYou can use Python 2.7 or Python 3.4. Second, there is now a baseurl option to add a prefix to generated local\nURLs. More info » . On the other hand, the checklist extension has been removed as it caused issues\nwith reference id resolution.", "title": "Urubu 0.7: Python 3 support, baseurl option", "url": "/news/2015-03-07.html" }, { "tags": "", "text": "Introducing Urubu, a Python-based micro CMS for static websites.\nRead about the rationale behind it .", "title": "Urubu 0.1 released", "url": "/news/2014-01-12.html" }, { "tags": "", "text": "Highlights: Add posibility to override output filename. (#51). See the saveas attribute\nin the manual .\nAn example usage, see How do I make a sitemap? . The urubu serve command is more secure. This is transparent to the user\n(#49). Added option for jinja2 to fail on undefined vars (#47). \nSee the strict_undefined attribute in the manual .", "title": "Urubu 1.3.0 released", "url": "/news/2016-11-14.html" }, { "tags": "", "text": "The highlight of this release is support for Templating constructs in pages .", "title": "Urubu 1.2.0 released", "url": "/news/2016-02-12.html" }, { "tags": "", "text": "Maintenance release: added test dependencies to setup.py, removed Python 2\ncompatibility layer, and relaxed the Markdown version pin to >= 3.0.", "title": "Urubu 1.4.1 released", "url": "/news/2026-03-30.html" }, { "tags": "", "text": "This is a bug-fix release.", "title": "Urubu 0.3.1 released", "url": "/news/2014-03-18.html" }, { "tags": "", "text": "This is a bug fix release.", "title": "Urubu 0.2.1 released", "url": "/news/2014-02-15.html" }, { "tags": "", "text": "Python3 only.", "title": "Urubu 1.4.0 released", "url": "/news/2024-12-30.html" }, { "tags": "", "text": "Release highlights: the urubu serve command automatically takes\nthe baseurl option into account (Pull request #27). when an undefined anchor is referred to in a page, a\nwarning is generated, just like for references to undefined pages (Issue #30). the layout attribute can be assigned null . In this\nway the page content can be used by other pages, but no html is generated for\nthe page itself. In addition, a significant effort was put into development robustness. In\nparticular, a regression test suite has been added. This is based on py.test and tox , so that both Python 2.7 and 3.4 are verified.", "title": "Urubu 0.8 released", "url": "/news/2015-11-22.html" }, { "tags": "", "text": "This release adds experimental support for the tag. Read more in the manual: Support for the mark tag and in this blog post .", "title": "Urubu 1.1.0 released", "url": "/news/2016-01-10.html" }, { "tags": "", "text": "This release adds support for the process_info Python hook. This hook\nprovides a powerful way to assist in templating. Basically, it provides full\nPython power to inspect, verify, modify, and add page attributes. For example,\nyou can use it to define a default layout , or a specific layout for pages in a certain directory. Read more in the manual: The process_info hook . There is also a new keep_files configuration attribute, that lets you\npreserve files that would otherwise be ignored. See the documentation .", "title": "Urubu 1.0.0 released", "url": "/news/2016-01-01.html" }, { "tags": "", "text": "Urubu 0.6 improves on wiki links: now you can link to a location within a page. Read my blog post for more info.", "title": "Urubu 0.6 released", "url": "/news/2015-01-28.html" }, { "tags": "", "text": "", "title": "Newsfeed", "url": "/news/index.html" }, { "tags": "", "text": "This release adds support for github-style task lists.", "title": "Urubu 0.2 released", "url": "/news/2014-01-22.html" }, { "tags": "", "text": "Release features: Run urubu serve from the top-level project directory. Programmable file extensions for site pages Introducing Urubu Quickstart : a quick way to set up a new Urubu project.", "title": "Urubu 0.4 and Urubu Quickstart released", "url": "/news/2014-05-25.html" }, { "tags": "", "text": "I created Urubu to solve a personal problem: how to create and maintain\nwebsites for my projects. I open-sourced it \"in the hope it can be useful\". On\nthis page I list a number of websites that are powered by Urubu. By others Sigasi Insights - Documentation for Sigasi's tools. Leonardo Uieda - Website about Leonardo's professional activities. PINGA lab - Site for the PINGA lab, a research group studying inverse\nproblems in geophysics. For others, by me Vlaamse sofrologen - Site of the flemish sophrologists (in Dutch) Troca Vins Naturels - Natural wines MyHDL MyHDL website - all about MyHDL, for users MyHDL development website - info for MyHDL developers Urubu Urubu Quickstart - the Quickstart companion site for Urubu Urubu Documentation - this site Personal Jan Decaluwe My site about professional activities Jan Decaluwe / Music My music projects Jan Decaluwe / Opinions My opinions, in Dutch", "title": "Websites powered by Urubu", "url": "/more/sites.html" }, { "tags": "", "text": "Author The Urubu software is written by Jan Decaluwe . License The Urubu software is licensed under the GNU Affero General Public License . The content on this documentation website is licensed\nunder the CC-BY-SA License . Development The Urubu software is developed on GitHub in the Urubu repo . The documentation is developed as a website in a gh-pages branch in the same\nrepo. It can be accessed from the custom domain urubu.jandecaluwe.com but it\nis hosted on GitHub Pages . Theme The theme on this website uses the Bootstrap framework,\nand is based on stock Bootstrap . Trivia An urubu is a brazilian vulture. Urubu is also the 10th album of\nAntonio Carlos Jobim, one of my favorite song composers.", "title": "About this site", "url": "/more/about.html" }, { "tags": "", "text": "GitHub repository Websites powered by Urubu About this site", "title": "More", "url": "/more/index.html" }, { "tags": "", "text": "Introduction Urubu implements a number of Markdown extensions. These extensions do not\nchange or extend the Markdown syntax. Rather, they add interesting features by\nprocessing and rendering the Markdown source in more sophisticated ways. The extensions are described in more detail below. Project-wide reference ids Urubu implements a Markdown extension to resolve project-wide reference ids.\nThis means that all pages in the project are automatically available as\nreference ids, and can be referred to using Markdown's syntax for reference\nlinks. This feature is described in more detail in the sections Project-wide reference ids and Reference links . It is Urubu's most important extension and a fundamental feature of the\ntool. Bootstrap-specific extensions Urubu is designed to play well with Bootstrap . To use certain Bootstrap\nfeatures, it has extensions that add Bootstrap classes to certain tags.\nMore specifically, the following classes are added: table Added to the tag. This defines basic styling for tables. dl-horizontal Added to the
tag that defines definition lists. This creates \na horizontal layout for definition lists in wide viewports. Support for the mark tag The html5 specification added a new tag to highlight text : the tag. For a good explanation of its purpose and the differences with the and tags, see this answer on Stack Overflow . Urubu supports lightweight markup for this tag by taking advantage of a\nredundancy in Markdown. In standard Markdown, you can either use asterisks\n( * ) or underscores ( _ ) to indicate emphasis. With the Urubu extension, the\nunderscore ( _ ) version is rendered using instead. This is an experimental feature that may be taken out if there are\nserious objections, although at this point there do not seem to be\ndisadvantages. To disable the feature, the mark_tag_support variable\ncan be set to false in the _site.yml file.", "title": "Markdown extensions", "url": "/manual/extensions.html" }, { "tags": "", "text": "The project directory A typical Urubu project directory looks as follows: Makefile\n_site.yml\n_layouts/_base.html\n page.html\n ...\n_python/__init__.py\n validators.py\n filters.py\ncss/...\njs/...\nindex.md\nfolder1/index.md\n file1.md\n pic1.png\n ...\nfolder2/index.md\n file2.md\n file3.md\n ... Files and directories with pathnames starting with an underscore _ are\nspecial. They are used during processing, but excluded from the built website.\nTheir function will be discussed below. The css and js directories are just an example of how CSS style sheets and\njavascript files could be organized. You can use any organization that you\nprefer. Content files are in Markdown format and should have the .md extension. You\nhave complete freedom in organizing them in directories. However, every\ndirectory should have an index.md file, including the top-level directory. Processing rules Urubu generates a website by processing the files and directory in the project\ndirectory, and putting the result in a _build subdirectory. The processing\ndepends on the pathname as follows: a Makefile is ignored and not copied to the build. files and directories starting with a dot . or\nunderscore _ are ignored and not copied to the build. Markdown files with extension .md are converted to a\nhtml file that is put into the build in the same relative location. all other files and directories are copied unmodified to the build in the\nsame relative location. As a result of the project organization and the build process, the structure of\nthe build matches the structure of the project directory. The relative\nlocation of all files is thus preserved. Special files and directories _site.yml This file contains site configuration info in YAML format.\nCurrently, these are the predefined attributes: Attribute Description reflinks Holds a mapping from reference ids to link objects. baseurl Prefix for generated local URLs file_ext Change default file extension ( '.html' ) for processed .md files link_ext Change default file extension ( '.html' ) for links to site's pages ignore_patterns List of additional file names or globs to be ignored during processing keep_files List of explicit file names be kept, overriding any ignores strict_undefined Set the default behavior regarding undefined template variables Link objects, for the reflinks attribute, are a mapping with an url key that maps\nto the link URL and a title key that maps to the link title. The baseurl option mirrors the same feature in Jekyll . It\nallows you to specify a prefix for all local URLs generated within your site.\nThis is necessary when your site will be served from a URL that has more than\njust the hostname. For example, on GitHub Pages sites are served from\nhttp://username.github.io/project_name/, so Urubu needs to include that /project_name/ in generated URLs pointing to local content. baseurl should be specified with no beginning or trailing slashes, e.g.: baseurl : prefix The file extension attributes, file_ext and link_ext , are both usually set to the\nsame value (i.e. '.php' ), unless the target site has .htaccess rewrite rules that\naffect the file extensions. Examples of this are sites that internally redirect pages like www.test.com/account to www.test.com/account.htm . For this case, one would need to set file_ext to '.htm' , so Urubu generated files have the .htm extension, whereas link_ext would\nbe set to '' , so that the a href links are directed to the files without extension. Otherwise, file_ext and link_ext should be set to the same extension, specially\nduring testing, so that the simple web server invoked by urubu serve works fine,\nas well as any web server that does not rewrite the file extensions of the requests. The ignore_patterns attribute specifies glob-style patterns to be ignored\nduring processing, in addition to the default ones according to the Processing Rules . In some cases you may explicitly want to keep certain files that would normally\nbe ignored. For example, you may have hidden files like .nojekyll to prevent\nJekyll processing, or .htaccess and .htpasswd for access control. You can\nkeep such files in the build using the keep_files attribute. The strict_undefined attribute controls whether the build should\nsilently ignore undefined template variables or raise an error when they are\nencountered. If false or undefined, undefined template variables are treated\nas empty strings ( '' ). If true , the build will stop and raise an error. You can define additional attributes that will be made available as\nsite variables to the template engine. The following is an example of a _site.yml file: brand: Urubu\n\nreflinks:\n content_license:\n url: http://creativecommons.org/licenses/by-sa/3.0/\n title: CC-BY-SA License\n software_license:\n url: http://www.gnu.org/licenses/agpl-3.0.txt\n title: GNU Affero General Public License\n markdown:\n url: http://daringfireball.net/projects/markdown/\n title: Markdown\n\nfile_ext: '.htm' # Change default file extension ('.html')\nlink_ext: '.htm' # Change default link extension ('.html') _layouts This directory contains the available layouts.\nThey are used by the Jinja2 template engine to render html pages.\nThe layout files should have the .html extension. _python This directory contains Python hooks for the template engine. Project-wide reference ids Urubu has the concept of project-wide reference ids. You can use them to refer\nto link objects in your content and configuration. Their definition comes\nfrom two sources: global reference ids are mapped to link objects in the _site.yml configuration file, as discussed earlier. all content pages and folders objects have reference ids. Project-wide references ids live in a single namespace. For pages and folders,\nthe id is a root-relative pathname starting with a slash / and without file\nextension. By convention, global reference ids should not start with a / . In your content and configuration info, you can also use relative reference\nids. Urubu will resolve them depending on the file location in the project. In\ncase of a name clash with a global reference id, you will have to disambiguate\nby adding pathname components. In accordance with Markdown conventions, reference ids are case-insensitive. Content files Content files are Markdown files with extension .md . They should start with\nYAML front matter that defines a number of attributes, as in the following example: ---\ntitle: Read me first\nlayout: page\ndate: 2014-01-15\n---\n The following attributes are predefined: Attribute Description title Specifies the page title. Mandatory. layout Specifies the layout, without the .html extension, or null . Mandatory. date Specifies the date in YYYY-MM-DD format. Optional. tags A tag or list of tags for the content. saveas Allows overriding of the output filename. The layout attribute is mandatory, but can be given a null value.\nThis is useful when the page content is used by other pages, but\nno html output is required for the page itself. In addition, you can add arbitrary user-defined attributes. All attributes\nare made available as page object attributes to the template engine. Markdown in attributes Optionally, you can use markdown format in front matter attributes. Markdown\nprocessing is enabled by adding a .md suffix to the attribute. The resulting\nhtml code will be stored in a synthesized attribute without the .md suffix. For example: ---\ntitle:\nlayout: page\nsummary.md: |\n A summary of the page items as a list:\n\n * item 1\n * item 2\n * item 3\n--- After processing, the page object will have a summary attribute with the html\ncode. Index files Index files with basename index.md are a special kind of content files. They\nare used to specify the attributes and the content of a directory. There are\ntwo options to specify the content, explicitly with the content attribute or\nimplicitly using the order attribute. Attribute Description content Defines the content explicitly as a list of reference ids or local link objects. order Defines the attribute by which the content in the directory should be ordered. reverse Optional boolean attribute defines reverse order or not. Default is false . content and order are mutually exclusive; you should use one of the two options. A local link object is a mapping with either a url key to an url, or a ref key to a reference id as mandatory items. In addtion, you can specify a title\nwith a title key. The ordering attribute can be predefined or user-defined, but it should be\nspecified in each content file in the directory. As an example, you can\nspecify that the content of a directory should be ordered as blog by the\nfollowing front matter in the index file: ---\ntitle: Blog\nlayout: blog_index\norder: date\nreverse: true\n--- Tag directory The optional top-level directory called tag has a predefined meaning. Urubu\nuses the corresponding folder in the build to hold the tag-related content view\nthat it generates automatically. You can use the index file to set attributes\nsuch as the layout . However, the content will be generated by Urubu\nautomatically and needs not be set.", "title": "Project structure", "url": "/manual/structure.html" }, { "tags": "", "text": "There are times when an index file will contain more entries than you want to include in a single page. Pagination allows Urubu to automatically split that page into separate pages in your site. Usage To enable pagination, add an items_per_page attribute to the front matter of an index page. Also add either items_index or items_filter to say where the list of items should pull from. To pull from files in the current directory, with 5 items per page: items_per_page: 5\nitems_index: this To pull from a different index contents: items_per_page: 5\nitems_index: news\\index.md To filter the contents: items_per_page: 5\nitems_filter: mysteries time-loop New Page Variables Each of the pages generated by pagination will have three new variables available to layouts. numpages - the number of total pages generated prevpage - the previous page in the chain nextpage - the next page in the chain Example pagination controls The following is a sample of generating pagination controls in a layout:", "title": "Pagination", "url": "/manual/pagination.html" }, { "tags": "", "text": "Introduction Welcome to Urubu! My name is Jan Decaluwe and I am Urubu's author. Urubu is a micro CMS for static websites. The qualification \"micro* means that\nit has a small feature set, defined by what I need for my purposes. To know\nwhether it is the right tool for you, check out Overview . Urubu's design philosophy is radical reuse of great software and ideas from\nothers. In the following sections, I will describe its concepts and how\nthey are implemented. Authoring In Urubu, content is entered in Markdown format. This is a lightweight format\nthat feels like a natural way to write content in plain text. Markdown support in Urubu is implemented by the Python-Markdown package, that\nconverts the format to html. Urubu also supports the industry standard Markdown Extra extensions, with useful features such as tables and definition\nlists. Urubu supports nicely rendered code blocks, an essential feature for software\nprojects documentation. Fenced Code Blocks are provided by the Markdown Extra\nextensions. This lets you enter language-specific code blocks without the need\nfor indentation. The CodeHilite extension of Python-Markdown enables\nlanguage-specific syntax highlighting via the Pygments library. Configuration The configuration options in Urubu are kept minimal, in the spirit of \"There\nshould be one obvious way to do it\". Where used, the configuration format is\nYAML, implemented by the PyYAML library. Configuration is mostly distributed, in the sense that every content file\nshould have a front matter , that specifies the title, layout, date and so on.\nThis idea is found in many tools, but Urubu reuses the technique from Jekyll .\nYAML front matter is specified between two sets of triple dashes. Urubu extends this configuration technique by treating index files specially.\nEach folder in the site should have an index file (called index.md ) that\nspecifies the ordered folder content. This can be done explicitly by listing\nthe files, or implicitly by specifying how the files should be ordered. Templating With templates you specify the html layout for a particular type of a page.\nIn a template you can mix plain html with control structures and variable\ninterpolation. The actual html page is generated by evaluating the template\nwith the appropriate evaluation context provided by Urubu. Urubu uses the Jinja2 templating language library. Theming A theme refers to the general look and feel of a web site. Partially this is\ndefined by the templates as discussed above. The other part is defined in style\nsheets, with a technique known as Cascading Style Sheets (CSS). Basically\nthis is a sophisticated technique to define how the various html elements\nshould be rendered by the web browser. With Urubu, you are free to design and use your own style sheets. However, it\nhas been developed with Bootstrap in mind. Bootstrap is a\nprofessionally-designed framework with lots of useful predefined styles\ncomponents. Urubu generates html that is Bootstrap-friendly, and infers the\nappropriate template variables for certain Bootstrap components. A great feature of Bootstrap is that it is \"mobile first\". This means that your\nwebsite will automatically adapt to any platform - smartphone, tablet or\nwidescreen. A notable project is Bootswatch . This is a set of themes designed as drop-in\nreplacement for the stock bootstrap styles. This gives you an effortless\noption to change the look and feel of your website. Navigation I am a big fan of Steve Krug's book Don't make me think ,\nand I feel that the lessons from this book are still often ignored.\nActually, the lack of focus of other tools on these ideas are the\nmain reason why I wrote Urubu. A main concept is good navigation. Urubu supports various techniques\nby inferring navigation-oriented variables and making them available to\nthe template engine. Moreover, they work well with some well-defined\nand nicely style Bootstrap navigation components. In this way,\nyou can easily implement the following: a navbar for navigation between major sections table of contents of a page in a sidebar breadcrumbs previous and next pager buttons active page or section highlighting Other techniques, independent from Urubu, can also help. Note for example that\nthe sidebar on this page is \"affixed\": it moves as you scroll through the page,\nbut never leaves the viewport. (Note: this description assumes that the\nviewport is wide enough to accomodate the sidebar.) At any time, the full\nstructure of the page remains visible and available for navigation. This was\nimplemented by borrowing code from the Bootstrap theme. Project-wide reference ids Markdown defines the concept of a reference link. This is a way to refer to a\npage or an url using a reference id. The syntax of a reference link is a\nreference id between square brackets, for example [intro] . Urubu supports the concept of project-wide reference ids. First, global\nreference ids can be defined in the site configuration file. Moreover, all\ncontent pages and folders have a corresponding reference id: their pathname\nwithout extension. In this case, reference links are similar to wiki links, the\ntypical way to link between pages in wiki's. Standard Markdown only resolves reference ids that are defined within the file.\nUrubu extends this behavior by resolving them over the project. This feature\nis implemented as a Markdown extension. Note that it doesn't require new syntax. Project-wide reference ids are a unique Urubu feature. One of the messages of Steve Krug's book is that the text that you click should\nbe the title of the page where you land. Therefore, when you use reference\nlinks, Urubu will insert the page title in the generated html (unless you\nspecify an alternative text explicitly). Development and deployment You can develop a Urubu project is like a software project, from a git or\nmercurial repository. This gives you best-in-class revision control.\nMoreover, all the workflows that these systems provide are available. For\nexample, you can develop your website collaboratively on GitHub or Bitbucket . Finally, it is easy to automate deployment, triggered by a push\nof the generated site to an upstream repository.", "title": "Concepts", "url": "/manual/intro.html" }, { "tags": "", "text": "Urubu works with modern versions of Python 2 and Python 3 using the same\ncodebase. More specifically, it requires Python 2.7 or Python 3.4. You can install Urubu using pip: pip install urubu To upgrade an existing installation to the\nlatest version, use: pip install --upgrade urubu If pip is not yet available on your system, follow the pip installation\ninstructions . You may want to install Urubu in an isolated environment using virtualenv . Urubu depends on a number of libraries that will automatically be installed if\nnot yet available: Python-Markdown , PyYAML , Pygments and Jinja2 . For a quick way to set up a new Urubu project, visit Urubu Quickstart .", "title": "Installation", "url": "/manual/install.html" }, { "tags": "", "text": "Content In Urubu, content is entered in Markdown format. This is a lightweight format\nthat feels like a natural way to write content in plain text. Stock markdown has a small feature set. For example, it does not even\nsupport tables. For this reason, Urubu supports some extensions. In particular,\nit supports the Markdown Extra extensions that have become an industry\nstandard, as well as a few others. The most notable supported extensions are: Tables Attribute lists Abbrevations Definition Lists Fenced Code Blocks CodeHilite Code Urubu intents to offer good support for software projects. Therefore, it\nsupports nicely rendered code blocks. One part of the solution is Fenced Code Blocks , provided by the Markdown Extra\nextensions. This lets you enter language-specific code blocks without the need\nfor indentation. The second part is the CodeHilite extension of Python-Markdown. This\nextension enables language-specific syntax highlighting through the Pygments library. To properly render the highlighted code, you will need to add a syntax.css stylesheet. A good solution is to use the syntax stylesheet from\nGitHub . Reference links Stock Markdown supports \"reference links\" that are resolved by defining them\nlater in the file. For example, you can use [urubu] in your content and\nfurther on define it as follows: [urubu]: http://urubu.jandecaluwe.com This is nice for readability, but it all remains file based. Urubu extends this behavior by automatically resolving Project-wide reference ids . This feature is implemented as a Markdown extension. Note that\nit doesn't require a syntax change. It enables page linking like in wikis. In addition, you can add a fragment, like #some-anchor , to the reference id.\nThis represents a link to an anchor within a page. Since Urubu automatically\nadds slugified anchors to markdown headers, you can use those as targets. For\ninstance, [authoring#reference-links] is a link to the current Reference links section. You can also define your own anchors\nusing Attribute lists . Markdown supports reference links without a text. In that case, Urubu inserts\nan appropriate text in the html. For a reference link with no fragment, the\ntitle of the page is inserted. For a reference link with a fragment, the\nfragment text is inserted. To make the result more readable, you can use\nnon-slugified fragment text. For example, [authoring#Reference links] also\nlinks to the present section, and is rendered as Reference links .", "title": "Authoring", "url": "/manual/authoring.html" }, { "tags": "", "text": "Overview Writing in Markdown is great, but sometimes you run into limitations. For those\ncases, Urubu supports a feature gratefully borrowed from Jekyll : using\ntemplating constructs in content pages. Basically, all content pages are processed by the templating engine before\ngoing to the Markdown processor. The full power of Jinja2 is thus available\nin your content pages. The usage of templating constructs in content pages is best explained with\nexamples. Therefore, we will start with some examples, and review the concepts\nafterwards. Example usage Task list icons Suppose you want to emulate GitHub style task lists, as follows: Task 1 Task 2 Task 1 An icon is used to show whether a task is still open or not. We can support this by defining well-named reusable variables in a dedicated\ntemplate file, as follows: {% set open = '' %}\n{% set done = '' %} Variables open and done now hold HTML code that refers to icons. In these\nexamples, I use the Font Awesome icon library. You will need to add the\nappropriate reference to the icon stylesheet in your base template. Suppose these variables are defined in the file _layouts/util.html . We can\nimport them in any content page as follows: {% from 'util.html' import open, done %} Note that Urubu knows to look up util.html in the _layouts/ directory,\nbecause that is where templates should be located. Within the content page, we can use the variables as follows, to get the result\nas above: * {{ open }} Task 1\n* {{ done }} Task 2\n* {{ open }} Task 1 General icon interface Suppose you want a more general interface to icons, so that you can easily\nrefer to any icon by name. This can be done with a Jinja2 macro. A macro is\nlike a function that can take parameters: {% macro fa(name, class='') %}\n\n{% endmacro %} Again, we can import the macro fa in content pages: {% from 'util.html' import fa %} Then we can use it as follows, for example to refer to the Github icon: {{ fa('github') }} This gives the following result: We can pass additional CSS classes via the optional class parameter. The\nfollowing example gets the alternative Github icon in twice the basic size: {{ fa('github-alt', 'fa-2x') }} This gives the following result: Figure Standard Markdown does not support the HTML5
tag, and the related
tag to add captions. We can support this with the following\nmacro: {% macro figure(fn, caption='') %}\n
\n \"{{caption}}\"\n {% if caption %}\n
{{caption}}
\n {% endif %}\n
\n{% endmacro %} This macro assumes that images will be placed in an img/ directory. In\naddition, it makes the image responsive using a Bootstrap class, and centers\nthe optional caption. Again, we can use the macro by importing: {% from 'util.html' import figure %} This is an example usage: {{ figure('urubu.jpg', \"An Urubu - a brazilian vulture\") }} This gives the following result: An Urubu - a brazilian vulture Templating concepts Template processing is done first The examples illustrate how you can use template variables and macros to\nconstruct HTML code. However, it is important to understand that template\nprocessing is done first, before Markdown processing (for good reasons). Thus,\nthe HTML code from variables and macros first becomes part of Markdown source\ncode. This works well because Markdown is designed to handle HTML\ntransparently. Full template power available The examples demonstrate the use of variables, macros, and imports. This is\nmerely the beginning: in fact, the full power of Jinja2 templates is available.\nThis is a vast subject. To learn what is possible, see the Jinja2 Template\nDesigner Documentation . Context variables When Urubu invokes template processing on a page, it automatically passes\ncertain context variables. This works exactly like for regular templates, as\ndescribed in Context Variables . Basically, variable this provides access to the page attributes, and variable site provides access to\nthe global site attributes. Template delimiters Template support introduces new delimiters as follows: {# ... #} for comments not included in the output {{ ... }} for expressions, to print to the output {% ... %} for statements These delimiters deserve some attention. First, the comment delimiters are interesting because they add a functionality\nthat is not available in Markdown: comments that will not show up in the\noutput. Secondly, as always with delimiters, there is the problem of how to escape them\nif you want to use them literally in source code, without interpretation. For an inline literal or snippet you can use literal expressions. For example,\nto get {{ you can write {{ '{{' }} . For a larger section, you can mark a block raw . For example, to\nget the list shown earlier in this section, you can write: {% raw %}\n* `{# ... #}` for comments not included in the output\n* `{{ ... }}` for expressions, to print to the output\n* `{% ... %}` for statements\n{% endraw %}", "title": "Templating constructs in pages", "url": "/manual/templating-in-pages.html" }, { "tags": "", "text": "Overview Templates define the html layout for a particular page type. In a template you\ncan mix plain html with control structures and variable interpolation. The html\npage is generated by evaluating the template with the appropriate evaluation\ncontext, provided by Urubu. Templates are part of the website project setup. If you are a content\ncontributor, you may not have to worry about them. All you have to do is\nspecify the appropriate layout name in the YAML front matter of your content\nfiles. In general, it is better to do programming in Python code. However, for the\npurpose of generation of pages in a format such as html, this is not very\npractical. Therefore, a template contains both html and programming\nconstructs. Template programming is good for common tasks like the following: iteration over a list of items testing whether an item is defined filtering items, possibly with user-defined filters comparing the loop item object with the current object, to check whether it is active Urubu interacts with templates by providing an evaluation context with the\nappropriate objects. The goal is to make the job of the templates as easy as\npossible with ready-to-use object attributes. The template library Urubu uses the Jinja2 templating language library. Jinja2 has great documentation and you should\ncheck it out when using templates in Urubu. A great feature of Jinja2 is template inheritance. With this technique,\nyou can easily generate small variations of a parent template. Link objects Description Link objects are the primary objects that you use in templates. \nThey come in a number of flavours: Link object Description global link object Defined in the _site.yml file. local link object Defined locally in the content attribute of an index file. folder object Corresponds to a project subdirectory. page object Corresponds to a Markdown content file. tag folder object Dedicated folder for content ordered by tag. tag object Represents content corresponding to a specific tag. Attributes Link objects have attributes. The defined attributes depend on the type of the\nlink object. The following attributes are common to all link objects : Attribute Description url The url of the object. title The title of the object. All link objects except local link objects also\nhave an id attribute: Attribute Description id The unique id by which the object is known in the project. Folder and page objects have the following attributes: Attribute Description fn The pathname of the file or directory corresponding the object. components The components of the object's pathname, without file extension, as a list. mdate Modification date Folder objects also have a content attribute: Attribute Description content The content of the folder as a list of page & folder objects. In addition, all attributes specified in the YAML front matter\nof the corresponding index file will be available as attributes of\nthe folder object. Page objects have the following additional attributes: Attribute Description layout The template to render the object as a html file. body The page content in html. toc The table of contents of the page as an unordered html list. breadcrumbs Breadcrumbs as a list. The current page object is at position 0, the containing folder objects are at the higher positions. prev The previous page object in the content, or None if there is none next The next page object in the content, or None if there is none In addition, all attributes specified in the YAML front matter of the\ncorresponding content file are available as attributes of the page object. Index pages Index pages are associated with index.md files. They are special in the sense\nthat they define the attributes and the content of a folder. Therefore, they\nhave the same content attribute as the corresponding folder object. Tag objects Tag objects are inferred by Urubu automatically. They list the content\ncorresponding to a tag. Attribute Description id /tag/{{tag}} components [tag, {{tag}}] title tag tag tag layout tag content List of page & folder objects corresponding to tag . The tag content is ordered by date, most recent first. If the date is not\ndefined, the modification date is used as a fallback ( mdate attribute). The layout name is predefined to tag . You have to provide the tag.html template to trigger the rendering of tag objects. In the simplest case, it\nmay be sufficient to inherit from a general index layout. Tag folder object The tag folder object is a special top-level folder whose id is /tag . Urubu\ninfers tag-related content for this folder automatically. You can optionally create the corresponding directory in the source code, and\nuse the index file to set attributes such as the layout . In any case, Urubu\nwill create the object if tags are used, and infer the content attribute. Attribute Description id /tag components [tag] content A list of tag objects, inferred by Urubu. The content is ordered according to the content size of tag objects,\nthe largest one first. Context variables Urubu makes the context available to templates with\ntwo context variables. site This variable holds site-wide information. It has one predefined attribute: Attribute Description reflinks A mapping from all reference ids to link objects. Note that the id of the root object is / . Starting from there,\nyou can traverse the whole site. In addition, all the attributes specified in the _site.yml file\nwill be available as attributes of the site variable. this This variable holds the current page or tag object.", "title": "Templates", "url": "/manual/templates.html" }, { "tags": "", "text": "Alt Layouts are for when you want to create more than one physical .html file per .md file. This is most useful when the additional .html files do not depend on the content of the original page, but on the front matter attributes. Usage To enable alt layouts for a .md file, add an alt_layouts attribute to the front matter of a page. This is a list of objects containing two attributes, layout and location . The layout attribute gives the name of an alternate layout to use. The location attribute gives the directory where the .html file should be put. That directory must already exist in your directory structure. Also add either items_index or items_filter to say where the list of it Example The following is a sample of generating two additional .html files for a product page: layout: product\n\nalt_layouts:\n - layout: confirmation\n location: confirmations\n - layout: product_details\n location: details If the original foo.md file was in the products directory, three .html files would be generated: products/foo.html\nconfirmations/foo.html\ndetails/foo.html", "title": "Alt Layouts", "url": "/manual/alt_layouts.html" }, { "tags": "", "text": "The urubu command After installation, an urubu command will be available. If you prefer, you can call the installed package as a script using python -m\nurubu , with the same effect. Subcommands The urubu command supports two subcommands. Run these commands from the top\nlevel project directory. urubu build Build the website. The website will be in the _build subdirectory. urubu serve Start a local webserver to serve the website as you develop it. The website\nwill be available at localhost:8000 . Run this command in a separate terminal\nwindow, and kill the server when you are done. Development flow I prefer to put the commands in a Makefile, so that I can\nrun make to build and make serve to start a server. Currently, you have to build the site explicitly to see\nthe development changes in the browser.", "title": "Project building", "url": "/manual/building.html" }, { "tags": "", "text": "Introduction A static site cannot natively support dynamic services. Fortunately, it is\noften an elegant solution to integrate third party solutions within a\nstatic site. One of the most prominent examples is Search. One possibility is integrating an\nexternal service such as Google Custom Search. The disadvantage is that one has\neither to pay for it or accept the branding. As an alternative, Urubu supports Tipue Search, an open source solution based\non javascript executed in the browser. As part of the site building, Urubu\ngenerates a view on the searchable content. In this chapter, we describe how\nthe integration is accomplished. Installing Tipue Search The first step is to download the Tipue Search distribution. It contains a tipuesearch directory. Copy that directory to the top level of your project.\nAs usual, Urubu copies it to the built website, so that the required\nstylesheets and javascript files are available in the expected location. Do not rename the tipuesearch directory. The existence of that\ndirectory triggers Urubu's support. The search box The next step is to create a search box. Suppose you want to make it part of\nthe navbar, as in the present site. This is achieved with the following html\ncode:
\n
\n \n
\n The name and the id values in the tag of the search box are\nmandatory for Tipue Search. The typical place for this code would be in the\nnavbar code in a basic layout for the site. The search results page The next step is to create a search result page. To integrate it we first\ncreate a dedicated layout using template inheritance. Let us assume that is\nthere is a head_addon and a body_addon block to add links and scripts to\nthe section respectively. The search.html layout is\nthen as follows: {% extends \"page.html\" %}\n\n{% block head_addon %}\n\n{% endblock %}\n\n{% block body_addon %}\n\n\n\n\n{% endblock %} We inherit from a page.html layout. In the head_addon block, we add\nthe Tipue Search style sheet for the result page. In the body_addon page we\nadd the Tipue Search java script modules, and the inline script that generates\nthe results. This setup assumes that the jQuery javascript library itself is already loaded\nin the body of the parent layout, with a line like the following: If you use the Bootstrap javascript modules, that will be the case. In the top level project directory, we can then create a search.md files that\nuses the search.html layout and has the generated search results as its\ncontent: ---\ntitle: Search results\nlayout: search\n---\n\n
After building the site, there will be a functional search.html file in the\ntop-level directory. Note The tipuesearch.css stylesheet also contains styling for the search\nbox. The result may be undesirable if you use your own styling, like in the\npresent website. The workaround is to comment the search box styling out. The search content The searchable content itself is a JSON object defined in the file tipuesearch/tipuesearch_content.json . This is where Urubu kicks in: this\nfile is generated automatically. Extracting meaningful searchable content from a web site is not trivial. A\ndesign decision for Urubu was to use modern techniques to help with this. In\nparticular, Urubu will only consider content that is wrapped with the
tag. This is a relatively new html5 tag with exactly the purpose to indicate\nthe page content explicitly. The site designer should therefore review the site layouts and wrap all\nsearchable content with the
tag. Typically, this is the region were\nthe this.body variable is called in a template. Note The
tag is not supported in IE11. A popular workaround is to\nuse the html5shiv.js Javascript module. Layouts based on Bootstrap do\nthis already.", "title": "Adding Search", "url": "/manual/search.html" }, { "tags": "", "text": "Introduction Urubu supports Python hooks to make templating easier. Upon a build, it tries\nto import a _python module or package, and looks for hook variables with\npredefined names. The following hooks are defined: Variable Description filters A mapping from filter names to filter functions. process_info A function to inspect and process content file info. You have to make sure that these names are exported correctly. For example, if\nyou organize _python as a package, it could look as follows: _python/\n __init__.py\n filters.py\n hooks.py If filters is defined in filters.py , and process_info in hooks.py , the __init__.py file would contain: from .filters import filters\nfrom .hooks import process_info The filters hook Filters functions should be defined as custom filters in\nJinja2 . As a typical example, consider a filter that converts a date value into a\ndesired format. The filters.py module would contain the following: def dateformat(value, format=\"%d-%b-%Y\"):\n return value.strftime(format)\n\nfilters = {}\nfilters['dateformat'] = dateformat You can then use the dateformat filter in templates. The process_info hook The interface of the process_info function is as follows: def process(info, site):\n ... This function is called for every content file in the project. The site variable provides access to the site variables defined in _site.yml . The info variable contains the file content info as it is being\nconstructed by Urubu. At the moment of the call, the following\ninferred attributes are available: Attribute Description id The unique id by which the object is known in the project. url The url of the object. components The components of the object's pathname, without file extension, as a list. fn The pathname of the file or directory corresponding the object. mdate Modification date In addition, all attributes specified in the YAML front matter of the\ncorresponding content file are available as attributes of the info object. The site and info variables are Python dictionaries. This means that the\nattributes are available via key access, not via Python attribute access. This\nis because the YAML reader constructs Python dictionaries from the front\nmatter. The process_info function can can inspect the attributes, verify and modify\nthem, and add additional ones. process_info examples Defining a default layout It can be handy to define a default layout for the case this mandatory\nattribute is not specified in the content file. Suppose we want a default index layout for index files, and a page layout for other files: def process_info(info, site):\n if 'layout' not in info:\n if info['components'][-1] == 'index':\n info['layout'] = 'index'\n else:\n info['layout'] = 'page' Defining a specific layout Suppose we have a blog directory and we want to automatically define a\nspecific post layout for blog posts: def process_info(info, site):\n components = info['components']\n if len(components) == 2:\n if components[0] == 'blog' and components[1] != 'index':\n process_post(info)\n\ndef process_post(info):\n if not 'layout' in info:\n info['layout'] = 'post'", "title": "Python hooks", "url": "/manual/hooks.html" }, { "tags": "", "text": "Concepts Installation Project structure Authoring Project building Templates Templating constructs in pages Python hooks Markdown extensions Adding Search Pagination Alt Layouts", "title": "Manual", "url": "/manual/index.html" }, { "tags": "", "text": "The source structure of a project is preserved in the built website, and all\nnon-markdown content files are copied verbatim. See Project structure . Therefore, you can put media files at any convenient place in the source, and\nrefer to them using Markdown image syntax, with a relative or root-relative\npath to the source file.", "title": "How to add media files?", "url": "/faq/media-files.html" }, { "tags": "", "text": "To generate a sitemap you need to do the following: Create a markdown file called sitemap.md like this: ---\ntitle: sitemap\nlayout: sitemap\nchangefreq: monthly\npriority: 1.0\nxmlns: http://www.google.com/schemas/sitemap/0.84\nsaveas: sitemap.xml\n--- Provide a sitemap.html in the _layouts directory, with looking something like the following: \n\n{% for t in site.reflinks %}\n {% if site.reflinks[t].fn and not site.reflinks[t].hidden %}\n \n {{ site.hostname }}{{ site.reflinks[t].url }}\n {{ this.changefreq }}\n {{ this.priority }}\n \n {% endif %}\n{% endfor %}\n What makes this work is for the main part the saveas parameter in the sitemap.md file, which overrides the default output filename with sitemap.xml instead of sitemap.html . If you add other sitemaps don't forget to specify distinct id and saveas for each one, to prevent Ambiguous reference id errors.", "title": "How do I make a sitemap?", "url": "/faq/sitemap.html" }, { "tags": "", "text": "Yes, Urubu support links to page sections.\nRead this blog post to learn how.", "title": "Can I specify a link to a section in a page?", "url": "/faq/link2section.html" }, { "tags": "", "text": "Yes: you can easily use MathJax with Urubu. Read more about it here .", "title": "Is there a way to render formulas?", "url": "/faq/formulas.html" }, { "tags": "", "text": "Urubu is licensed under the GNU Affero General Public License . The first thing to understand is that this license applies only to the Urubu\nsoftware. It has no implications on website projects managed with Urubu. You\nare free to license your projects in any way you choose. The license only becomes relevant when you release a modified version of the\nUrubu software to the public in some way. In that case, you have to release the\nmodified source code also, under the same license. With the original GPL, a release meant shipping software to user that would\ninstall and run it locally. However, these days software is often made\navailable by running it on a server. Under the original GPL, there would be no\nrequirement to release the modified source code in such as case. This clearly\nviolates the spirit of the GNU Licenses. The GNU Affero General Public License fixes that problem. If you make the modified software\navailable by running it on a server, you have to make the modified source code\navailable to the users under the same license.", "title": "What are the licensing requirements?", "url": "/faq/licensing-requirements.html" }, { "tags": "", "text": "Urubu supports tags. To use them, you need 2 things: Assign the desired tags to content pages, by assigning a tag or\na list of tags to the tags attribute. See also: Content files . Provide a tag.html layout in the _layouts directory. It is the existence of the tag.html layout that triggers the generation of\ntag-related content. For example, if you have used tags bar and foo in the\nproject, you will see that the _build folder contains tag/bar/index.html and tag/foo/index.html . Those index files use the tag.html layout to show \nthe content related to a tag. Presumably, there is already a general index.html layout to show content in a\nfolder. An initial tag.html layout can then be a one-liner by using template\ninheritance, like so: {% extends \"index.html\" %} Of course, you may want to specialize the tag.html layout\nfurther to better reflect the purpose. Urubu also generates the corresponding tag objects so that you can use them in\nyour layouts. This is described in Tag objects . Note that the _build will contain a top-level tag folder, even when the\nsource directory does not. Optionally, you can define the tag folder in the\nsource also. You can then define an index file and set attributes such as the layout to display the tags themselves. However, the content will be\ngenerated by Urubu automatically and needs not be set. See also: Tag folder object .", "title": "How to use tags?", "url": "/faq/tags.html" }, { "tags": "", "text": "Urubu version 0.8 and higher The urubu serve command takes the baseurl setting automatically into\naccount. Urubu version 0.7 The urubu serve server does not include the baseurl prefix when serving\npages so sites that use baseurl can't be previewed locally using urubu\nserve . An alternative option is to use tservice , which includes an option to\nserve a local static site with a URL prefix. To use tservice with an Urubu\nsite instead of using urubu serve call tserve with the prefix option, e.g. tserve --prefix _build Where is your site's particular prefix.", "title": "How to preview sites that use the baseurl option?", "url": "/faq/baseurl-preview.html" }, { "tags": "", "text": "What are the licensing requirements? How to add media files? How to preview sites that use the baseurl option? Can I specify a link to a section in a page? Is there a way to render formulas? How to use tags? How do I make a sitemap?", "title": "FAQ", "url": "/faq/index.html" } ] } ================================================ FILE: doc/_build/tipuesearch/tipuesearch_set.js ================================================ /* Tipue Search 5.0 Copyright (c) 2015 Tipue Tipue Search is released under the MIT License http://www.tipue.com/search */ /* Stop words Stop words list from http://www.ranks.nl/stopwords */ var tipuesearch_stop_words = ["a", "about", "above", "after", "again", "against", "all", "am", "an", "and", "any", "are", "aren't", "as", "at", "be", "because", "been", "before", "being", "below", "between", "both", "but", "by", "can't", "cannot", "could", "couldn't", "did", "didn't", "do", "does", "doesn't", "doing", "don't", "down", "during", "each", "few", "for", "from", "further", "had", "hadn't", "has", "hasn't", "have", "haven't", "having", "he", "he'd", "he'll", "he's", "her", "here", "here's", "hers", "herself", "him", "himself", "his", "how", "how's", "i", "i'd", "i'll", "i'm", "i've", "if", "in", "into", "is", "isn't", "it", "it's", "its", "itself", "let's", "me", "more", "most", "mustn't", "my", "myself", "no", "nor", "not", "of", "off", "on", "once", "only", "or", "other", "ought", "our", "ours", "ourselves", "out", "over", "own", "same", "shan't", "she", "she'd", "she'll", "she's", "should", "shouldn't", "so", "some", "such", "than", "that", "that's", "the", "their", "theirs", "them", "themselves", "then", "there", "there's", "these", "they", "they'd", "they'll", "they're", "they've", "this", "those", "through", "to", "too", "under", "until", "up", "very", "was", "wasn't", "we", "we'd", "we'll", "we're", "we've", "were", "weren't", "what", "what's", "when", "when's", "where", "where's", "which", "while", "who", "who's", "whom", "why", "why's", "with", "won't", "would", "wouldn't", "you", "you'd", "you'll", "you're", "you've", "your", "yours", "yourself", "yourselves"]; // Word replace var tipuesearch_replace = {'words': [ {'word': 'tipua', 'replace_with': 'tipue'}, {'word': 'javscript', 'replace_with': 'javascript'}, {'word': 'jqeury', 'replace_with': 'jquery'} ]}; // Weighting var tipuesearch_weight = {'weight': [ {'url': 'http://www.tipue.com', 'score': 200}, {'url': 'http://www.tipue.com/search', 'score': 100}, {'url': 'http://www.tipue.com/about', 'score': 100} ]}; // Stemming var tipuesearch_stem = {'words': [ {'word': 'e-mail', 'stem': 'email'}, {'word': 'javascript', 'stem': 'jquery'}, {'word': 'javascript', 'stem': 'js'} ]}; // Internal strings var tipuesearch_string_1 = 'No title'; var tipuesearch_string_2 = 'Showing results for'; var tipuesearch_string_3 = 'Search instead for'; var tipuesearch_string_4 = '1 result'; var tipuesearch_string_5 = 'results'; var tipuesearch_string_6 = 'Prev'; var tipuesearch_string_7 = 'Next'; var tipuesearch_string_8 = 'Nothing found'; var tipuesearch_string_9 = 'Common words are largely ignored'; var tipuesearch_string_10 = 'Search too short'; var tipuesearch_string_11 = 'Should be one character or more'; var tipuesearch_string_12 = 'Should be'; var tipuesearch_string_13 = 'characters or more'; ================================================ FILE: doc/_layouts/_base.html ================================================ {{this.title}} {% set bootstrap = "3.1.1" %} {% if site.bootstrap %} {% set bootstrap = site.bootstrap %} {% endif %} {% if site.bootswatch %} {% set theme_path = "bootswatch/"+ bootstrap + '/' + site.bootswatch %} {% else %} {% set theme_path = "bootstrap/" + bootstrap + "/css" %} {% endif %} {% set url_prefix = '' %} {% if site.baseurl %} {% set url_prefix = '/' + site.baseurl %} {% endif %} {% include 'analytics.html' %} {% block head_addon %} {% endblock %} {% set navbar_style = "navbar-default" %} {% if site.navbar_inverse %} {% set navbar_style = "navbar-inverse" %} {% endif %} {% set navbar_right_items = 1 %} {% if site.navbar_right_items %} {% set navbar_right_items = site.navbar_right_items %} {% endif %} {% block body %} {% endblock %} {% block body_addon %} {% endblock %} ================================================ FILE: doc/_layouts/analytics.html ================================================ ================================================ FILE: doc/_layouts/footer.html ================================================ ================================================ FILE: doc/_layouts/home.html ================================================ {% extends "_base.html" %} {% block home %} {% endblock %} {% block body %}

{{this.title}}

{{this.tagline}}

{% set news = site.reflinks['/news'].content[0] %}

{{news.date|dateformat}}: {{news.title}}

{{this.body}}
{% include 'footer.html' %} {% endblock %} ================================================ FILE: doc/_layouts/index.html ================================================ {% extends "_base.html" %} {% block body %} {% block jumbotron %}

{{this.title}}

{{this.abstract}}

{% endblock %}
{% for item in this.content %}

{{item.title}}

{{item.abstract}}

{% endfor %}
{% endblock %} ================================================ FILE: doc/_layouts/newsfeed.html ================================================ {% extends "_base.html" %} {% block body %}
{% for item in this.content %}

{{item.date|dateformat}}  {{item.title}}

{{item.body}}
{% endfor %}
{% include 'footer.html' %}
{% block breadcrumbs %} {% endblock %}
{% block content %}
{{this.body}}
{% if this.pager %} {% endif %}
{% endblock %} {% block sidebar %} {% if this.toc %} {% endif %} {% endblock %}
{% include 'footer.html' %} {% endblock %} ================================================ FILE: doc/_layouts/search.html ================================================ {% extends "page.html" %} {% block head_addon %} {% endblock %} {% block body_addon %} {% endblock %} ================================================ FILE: doc/_layouts/sharing.html ================================================
================================================ FILE: doc/_layouts/simple_page.html ================================================ {% extends "page.html" %} {% block sidebar %} {% endblock %} ================================================ FILE: doc/_layouts/util.html ================================================ {# task list icons #} {% set open = '' %} {% set done = '' %} {# general font awesome icon interface #} {% macro fa(name, class='') %} {% endmacro %} {# figure support #} {% macro figure(fn, caption='') %}
{{caption}} {% if caption %}
{{caption}}
{% endif %}
{% endmacro %} ================================================ FILE: doc/_python/__init__.py ================================================ from .filters import filters from .hooks import process_info ================================================ FILE: doc/_python/filters.py ================================================ def dateformat(value, format="%d-%b-%Y"): return value.strftime(format) filters = {} filters['dateformat'] = dateformat ================================================ FILE: doc/_python/hooks.py ================================================ def process_info(info, site): if 'layout' not in info: if info['components'][-1] == 'index': info['layout'] = 'index' else: info['layout'] = 'page' ================================================ FILE: doc/_site.yml ================================================ brand: Urubu bootswatch: null navbar_inverse: false navbar_right_items: 1 bootstrap: 3.3.4 keep_files: [ .nojekyll ] reflinks: jandecaluwe: url: http://www.jandecaluwe.com title: Jan Decaluwe myhdl_site: url: http://www.myhdl.org title: MyHDL website dev_myhdl_site: url: http://dev.myhdl.org title: MyHDL development website content_license: url: http://creativecommons.org/licenses/by-sa/3.0/ title: CC-BY-SA License software_license: url: http://www.gnu.org/licenses/agpl-3.0.txt title: GNU Affero General Public License bitbucket: url: http://www.bitbucket.com title: Bitbucket github: url: http://www.github.com title: GitHub markdown: url: http://daringfireball.net/projects/markdown/ title: Markdown markdown_extra: url: http://python-markdown.github.io/extensions/extra/ title: Markdown Extra python_markdown: url: http://python-markdown.github.io/ title: Python-Markdown pygments: url: http://pygments.org title: Pygments jinja2: url: http://jinja.pocoo.org title: Jinja2 bootstrap: url: http://getbootstrap.com title: Bootstrap bootswatch: url: http://bootswatch.com title: Bootswatch pyyaml: url: http://pyyaml.org title: PyYAML jekyll: url: http://jekyllrb.com title: Jekyll pelican: url: http://getpelican.com title: Pelican virtualenv: url: http://www.virtualenv.org/en/latest/virtualenv.html title: virtualenv urubu-repo: url: https://github.com/jandecaluwe/urubu title: Urubu repo tables: url: http://python-markdown.github.io/extensions/tables/ title: Tables abbrev: url: http://python-markdown.github.io/extensions/abbreviations/ title: Abbrevations attr_list: url: http://python-markdown.github.io/extensions/attr_list/ title: Attribute lists def_list: url: http://python-markdown.github.io/extensions/definition_lists/ title: Definition Lists fenced_code: url: http://python-markdown.github.io/extensions/fenced_code_blocks/ title: Fenced Code Blocks markdown_checklist: url: https://github.com/FND/markdown-checklist title: GitHub style Task Lists code_hilite: url: http://python-markdown.github.io/extensions/code_hilite/ title: CodeHilite urubu-quickstart: url: http://urubu-quickstart.jandecaluwe.com title: Urubu Quickstart urubu: url: http://urubu.jandecaluwe.com title: Urubu Documentation font-awesome: url: http://fortawesome.github.io/Font-Awesome title: Font Awesome ================================================ FILE: doc/css/bootstrap.css ================================================ /*! * Bootstrap v3.4.1 (https://getbootstrap.com/) * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ /*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ html { font-family: sans-serif; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; } body { margin: 0; } article, aside, details, figcaption, figure, footer, header, hgroup, main, menu, nav, section, summary { display: block; } audio, canvas, progress, video { display: inline-block; vertical-align: baseline; } audio:not([controls]) { display: none; height: 0; } [hidden], template { display: none; } a { background-color: transparent; } a:active, a:hover { outline: 0; } abbr[title] { border-bottom: none; text-decoration: underline; -webkit-text-decoration: underline dotted; -moz-text-decoration: underline dotted; text-decoration: underline dotted; } b, strong { font-weight: bold; } dfn { font-style: italic; } h1 { font-size: 2em; margin: 0.67em 0; } mark { background: #ff0; color: #000; } small { font-size: 80%; } sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } sup { top: -0.5em; } sub { bottom: -0.25em; } img { border: 0; } svg:not(:root) { overflow: hidden; } figure { margin: 1em 40px; } hr { -webkit-box-sizing: content-box; -moz-box-sizing: content-box; box-sizing: content-box; height: 0; } pre { overflow: auto; } code, kbd, pre, samp { font-family: monospace, monospace; font-size: 1em; } button, input, optgroup, select, textarea { color: inherit; font: inherit; margin: 0; } button { overflow: visible; } button, select { text-transform: none; } button, html input[type="button"], input[type="reset"], input[type="submit"] { -webkit-appearance: button; cursor: pointer; } button[disabled], html input[disabled] { cursor: default; } button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; } input { line-height: normal; } input[type="checkbox"], input[type="radio"] { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; padding: 0; } input[type="number"]::-webkit-inner-spin-button, input[type="number"]::-webkit-outer-spin-button { height: auto; } input[type="search"] { -webkit-appearance: textfield; -webkit-box-sizing: content-box; -moz-box-sizing: content-box; box-sizing: content-box; } input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; } fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; } legend { border: 0; padding: 0; } textarea { overflow: auto; } optgroup { font-weight: bold; } table { border-collapse: collapse; border-spacing: 0; } td, th { padding: 0; } /*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ @media print { *, *:before, *:after { color: #000 !important; text-shadow: none !important; background: transparent !important; -webkit-box-shadow: none !important; box-shadow: none !important; } a, a:visited { text-decoration: underline; } a[href]:after { content: " (" attr(href) ")"; } abbr[title]:after { content: " (" attr(title) ")"; } a[href^="#"]:after, a[href^="javascript:"]:after { content: ""; } pre, blockquote { border: 1px solid #999; page-break-inside: avoid; } thead { display: table-header-group; } tr, img { page-break-inside: avoid; } img { max-width: 100% !important; } p, h2, h3 { orphans: 3; widows: 3; } h2, h3 { page-break-after: avoid; } .navbar { display: none; } .btn > .caret, .dropup > .btn > .caret { border-top-color: #000 !important; } .label { border: 1px solid #000; } .table { border-collapse: collapse !important; } .table td, .table th { background-color: #fff !important; } .table-bordered th, .table-bordered td { border: 1px solid #ddd !important; } } @font-face { font-family: "Glyphicons Halflings"; src: url("../fonts/glyphicons-halflings-regular.eot"); src: url("../fonts/glyphicons-halflings-regular.eot?#iefix") format("embedded-opentype"), url("../fonts/glyphicons-halflings-regular.woff2") format("woff2"), url("../fonts/glyphicons-halflings-regular.woff") format("woff"), url("../fonts/glyphicons-halflings-regular.ttf") format("truetype"), url("../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular") format("svg"); } .glyphicon { position: relative; top: 1px; display: inline-block; font-family: "Glyphicons Halflings"; font-style: normal; font-weight: 400; line-height: 1; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } .glyphicon-asterisk:before { content: "\002a"; } .glyphicon-plus:before { content: "\002b"; } .glyphicon-euro:before, .glyphicon-eur:before { content: "\20ac"; } .glyphicon-minus:before { content: "\2212"; } .glyphicon-cloud:before { content: "\2601"; } .glyphicon-envelope:before { content: "\2709"; } .glyphicon-pencil:before { content: "\270f"; } .glyphicon-glass:before { content: "\e001"; } .glyphicon-music:before { content: "\e002"; } .glyphicon-search:before { content: "\e003"; } .glyphicon-heart:before { content: "\e005"; } .glyphicon-star:before { content: "\e006"; } .glyphicon-star-empty:before { content: "\e007"; } .glyphicon-user:before { content: "\e008"; } .glyphicon-film:before { content: "\e009"; } .glyphicon-th-large:before { content: "\e010"; } .glyphicon-th:before { content: "\e011"; } .glyphicon-th-list:before { content: "\e012"; } .glyphicon-ok:before { content: "\e013"; } .glyphicon-remove:before { content: "\e014"; } .glyphicon-zoom-in:before { content: "\e015"; } .glyphicon-zoom-out:before { content: "\e016"; } .glyphicon-off:before { content: "\e017"; } .glyphicon-signal:before { content: "\e018"; } .glyphicon-cog:before { content: "\e019"; } .glyphicon-trash:before { content: "\e020"; } .glyphicon-home:before { content: "\e021"; } .glyphicon-file:before { content: "\e022"; } .glyphicon-time:before { content: "\e023"; } .glyphicon-road:before { content: "\e024"; } .glyphicon-download-alt:before { content: "\e025"; } .glyphicon-download:before { content: "\e026"; } .glyphicon-upload:before { content: "\e027"; } .glyphicon-inbox:before { content: "\e028"; } .glyphicon-play-circle:before { content: "\e029"; } .glyphicon-repeat:before { content: "\e030"; } .glyphicon-refresh:before { content: "\e031"; } .glyphicon-list-alt:before { content: "\e032"; } .glyphicon-lock:before { content: "\e033"; } .glyphicon-flag:before { content: "\e034"; } .glyphicon-headphones:before { content: "\e035"; } .glyphicon-volume-off:before { content: "\e036"; } .glyphicon-volume-down:before { content: "\e037"; } .glyphicon-volume-up:before { content: "\e038"; } .glyphicon-qrcode:before { content: "\e039"; } .glyphicon-barcode:before { content: "\e040"; } .glyphicon-tag:before { content: "\e041"; } .glyphicon-tags:before { content: "\e042"; } .glyphicon-book:before { content: "\e043"; } .glyphicon-bookmark:before { content: "\e044"; } .glyphicon-print:before { content: "\e045"; } .glyphicon-camera:before { content: "\e046"; } .glyphicon-font:before { content: "\e047"; } .glyphicon-bold:before { content: "\e048"; } .glyphicon-italic:before { content: "\e049"; } .glyphicon-text-height:before { content: "\e050"; } .glyphicon-text-width:before { content: "\e051"; } .glyphicon-align-left:before { content: "\e052"; } .glyphicon-align-center:before { content: "\e053"; } .glyphicon-align-right:before { content: "\e054"; } .glyphicon-align-justify:before { content: "\e055"; } .glyphicon-list:before { content: "\e056"; } .glyphicon-indent-left:before { content: "\e057"; } .glyphicon-indent-right:before { content: "\e058"; } .glyphicon-facetime-video:before { content: "\e059"; } .glyphicon-picture:before { content: "\e060"; } .glyphicon-map-marker:before { content: "\e062"; } .glyphicon-adjust:before { content: "\e063"; } .glyphicon-tint:before { content: "\e064"; } .glyphicon-edit:before { content: "\e065"; } .glyphicon-share:before { content: "\e066"; } .glyphicon-check:before { content: "\e067"; } .glyphicon-move:before { content: "\e068"; } .glyphicon-step-backward:before { content: "\e069"; } .glyphicon-fast-backward:before { content: "\e070"; } .glyphicon-backward:before { content: "\e071"; } .glyphicon-play:before { content: "\e072"; } .glyphicon-pause:before { content: "\e073"; } .glyphicon-stop:before { content: "\e074"; } .glyphicon-forward:before { content: "\e075"; } .glyphicon-fast-forward:before { content: "\e076"; } .glyphicon-step-forward:before { content: "\e077"; } .glyphicon-eject:before { content: "\e078"; } .glyphicon-chevron-left:before { content: "\e079"; } .glyphicon-chevron-right:before { content: "\e080"; } .glyphicon-plus-sign:before { content: "\e081"; } .glyphicon-minus-sign:before { content: "\e082"; } .glyphicon-remove-sign:before { content: "\e083"; } .glyphicon-ok-sign:before { content: "\e084"; } .glyphicon-question-sign:before { content: "\e085"; } .glyphicon-info-sign:before { content: "\e086"; } .glyphicon-screenshot:before { content: "\e087"; } .glyphicon-remove-circle:before { content: "\e088"; } .glyphicon-ok-circle:before { content: "\e089"; } .glyphicon-ban-circle:before { content: "\e090"; } .glyphicon-arrow-left:before { content: "\e091"; } .glyphicon-arrow-right:before { content: "\e092"; } .glyphicon-arrow-up:before { content: "\e093"; } .glyphicon-arrow-down:before { content: "\e094"; } .glyphicon-share-alt:before { content: "\e095"; } .glyphicon-resize-full:before { content: "\e096"; } .glyphicon-resize-small:before { content: "\e097"; } .glyphicon-exclamation-sign:before { content: "\e101"; } .glyphicon-gift:before { content: "\e102"; } .glyphicon-leaf:before { content: "\e103"; } .glyphicon-fire:before { content: "\e104"; } .glyphicon-eye-open:before { content: "\e105"; } .glyphicon-eye-close:before { content: "\e106"; } .glyphicon-warning-sign:before { content: "\e107"; } .glyphicon-plane:before { content: "\e108"; } .glyphicon-calendar:before { content: "\e109"; } .glyphicon-random:before { content: "\e110"; } .glyphicon-comment:before { content: "\e111"; } .glyphicon-magnet:before { content: "\e112"; } .glyphicon-chevron-up:before { content: "\e113"; } .glyphicon-chevron-down:before { content: "\e114"; } .glyphicon-retweet:before { content: "\e115"; } .glyphicon-shopping-cart:before { content: "\e116"; } .glyphicon-folder-close:before { content: "\e117"; } .glyphicon-folder-open:before { content: "\e118"; } .glyphicon-resize-vertical:before { content: "\e119"; } .glyphicon-resize-horizontal:before { content: "\e120"; } .glyphicon-hdd:before { content: "\e121"; } .glyphicon-bullhorn:before { content: "\e122"; } .glyphicon-bell:before { content: "\e123"; } .glyphicon-certificate:before { content: "\e124"; } .glyphicon-thumbs-up:before { content: "\e125"; } .glyphicon-thumbs-down:before { content: "\e126"; } .glyphicon-hand-right:before { content: "\e127"; } .glyphicon-hand-left:before { content: "\e128"; } .glyphicon-hand-up:before { content: "\e129"; } .glyphicon-hand-down:before { content: "\e130"; } .glyphicon-circle-arrow-right:before { content: "\e131"; } .glyphicon-circle-arrow-left:before { content: "\e132"; } .glyphicon-circle-arrow-up:before { content: "\e133"; } .glyphicon-circle-arrow-down:before { content: "\e134"; } .glyphicon-globe:before { content: "\e135"; } .glyphicon-wrench:before { content: "\e136"; } .glyphicon-tasks:before { content: "\e137"; } .glyphicon-filter:before { content: "\e138"; } .glyphicon-briefcase:before { content: "\e139"; } .glyphicon-fullscreen:before { content: "\e140"; } .glyphicon-dashboard:before { content: "\e141"; } .glyphicon-paperclip:before { content: "\e142"; } .glyphicon-heart-empty:before { content: "\e143"; } .glyphicon-link:before { content: "\e144"; } .glyphicon-phone:before { content: "\e145"; } .glyphicon-pushpin:before { content: "\e146"; } .glyphicon-usd:before { content: "\e148"; } .glyphicon-gbp:before { content: "\e149"; } .glyphicon-sort:before { content: "\e150"; } .glyphicon-sort-by-alphabet:before { content: "\e151"; } .glyphicon-sort-by-alphabet-alt:before { content: "\e152"; } .glyphicon-sort-by-order:before { content: "\e153"; } .glyphicon-sort-by-order-alt:before { content: "\e154"; } .glyphicon-sort-by-attributes:before { content: "\e155"; } .glyphicon-sort-by-attributes-alt:before { content: "\e156"; } .glyphicon-unchecked:before { content: "\e157"; } .glyphicon-expand:before { content: "\e158"; } .glyphicon-collapse-down:before { content: "\e159"; } .glyphicon-collapse-up:before { content: "\e160"; } .glyphicon-log-in:before { content: "\e161"; } .glyphicon-flash:before { content: "\e162"; } .glyphicon-log-out:before { content: "\e163"; } .glyphicon-new-window:before { content: "\e164"; } .glyphicon-record:before { content: "\e165"; } .glyphicon-save:before { content: "\e166"; } .glyphicon-open:before { content: "\e167"; } .glyphicon-saved:before { content: "\e168"; } .glyphicon-import:before { content: "\e169"; } .glyphicon-export:before { content: "\e170"; } .glyphicon-send:before { content: "\e171"; } .glyphicon-floppy-disk:before { content: "\e172"; } .glyphicon-floppy-saved:before { content: "\e173"; } .glyphicon-floppy-remove:before { content: "\e174"; } .glyphicon-floppy-save:before { content: "\e175"; } .glyphicon-floppy-open:before { content: "\e176"; } .glyphicon-credit-card:before { content: "\e177"; } .glyphicon-transfer:before { content: "\e178"; } .glyphicon-cutlery:before { content: "\e179"; } .glyphicon-header:before { content: "\e180"; } .glyphicon-compressed:before { content: "\e181"; } .glyphicon-earphone:before { content: "\e182"; } .glyphicon-phone-alt:before { content: "\e183"; } .glyphicon-tower:before { content: "\e184"; } .glyphicon-stats:before { content: "\e185"; } .glyphicon-sd-video:before { content: "\e186"; } .glyphicon-hd-video:before { content: "\e187"; } .glyphicon-subtitles:before { content: "\e188"; } .glyphicon-sound-stereo:before { content: "\e189"; } .glyphicon-sound-dolby:before { content: "\e190"; } .glyphicon-sound-5-1:before { content: "\e191"; } .glyphicon-sound-6-1:before { content: "\e192"; } .glyphicon-sound-7-1:before { content: "\e193"; } .glyphicon-copyright-mark:before { content: "\e194"; } .glyphicon-registration-mark:before { content: "\e195"; } .glyphicon-cloud-download:before { content: "\e197"; } .glyphicon-cloud-upload:before { content: "\e198"; } .glyphicon-tree-conifer:before { content: "\e199"; } .glyphicon-tree-deciduous:before { content: "\e200"; } .glyphicon-cd:before { content: "\e201"; } .glyphicon-save-file:before { content: "\e202"; } .glyphicon-open-file:before { content: "\e203"; } .glyphicon-level-up:before { content: "\e204"; } .glyphicon-copy:before { content: "\e205"; } .glyphicon-paste:before { content: "\e206"; } .glyphicon-alert:before { content: "\e209"; } .glyphicon-equalizer:before { content: "\e210"; } .glyphicon-king:before { content: "\e211"; } .glyphicon-queen:before { content: "\e212"; } .glyphicon-pawn:before { content: "\e213"; } .glyphicon-bishop:before { content: "\e214"; } .glyphicon-knight:before { content: "\e215"; } .glyphicon-baby-formula:before { content: "\e216"; } .glyphicon-tent:before { content: "\26fa"; } .glyphicon-blackboard:before { content: "\e218"; } .glyphicon-bed:before { content: "\e219"; } .glyphicon-apple:before { content: "\f8ff"; } .glyphicon-erase:before { content: "\e221"; } .glyphicon-hourglass:before { content: "\231b"; } .glyphicon-lamp:before { content: "\e223"; } .glyphicon-duplicate:before { content: "\e224"; } .glyphicon-piggy-bank:before { content: "\e225"; } .glyphicon-scissors:before { content: "\e226"; } .glyphicon-bitcoin:before { content: "\e227"; } .glyphicon-btc:before { content: "\e227"; } .glyphicon-xbt:before { content: "\e227"; } .glyphicon-yen:before { content: "\00a5"; } .glyphicon-jpy:before { content: "\00a5"; } .glyphicon-ruble:before { content: "\20bd"; } .glyphicon-rub:before { content: "\20bd"; } .glyphicon-scale:before { content: "\e230"; } .glyphicon-ice-lolly:before { content: "\e231"; } .glyphicon-ice-lolly-tasted:before { content: "\e232"; } .glyphicon-education:before { content: "\e233"; } .glyphicon-option-horizontal:before { content: "\e234"; } .glyphicon-option-vertical:before { content: "\e235"; } .glyphicon-menu-hamburger:before { content: "\e236"; } .glyphicon-modal-window:before { content: "\e237"; } .glyphicon-oil:before { content: "\e238"; } .glyphicon-grain:before { content: "\e239"; } .glyphicon-sunglasses:before { content: "\e240"; } .glyphicon-text-size:before { content: "\e241"; } .glyphicon-text-color:before { content: "\e242"; } .glyphicon-text-background:before { content: "\e243"; } .glyphicon-object-align-top:before { content: "\e244"; } .glyphicon-object-align-bottom:before { content: "\e245"; } .glyphicon-object-align-horizontal:before { content: "\e246"; } .glyphicon-object-align-left:before { content: "\e247"; } .glyphicon-object-align-vertical:before { content: "\e248"; } .glyphicon-object-align-right:before { content: "\e249"; } .glyphicon-triangle-right:before { content: "\e250"; } .glyphicon-triangle-left:before { content: "\e251"; } .glyphicon-triangle-bottom:before { content: "\e252"; } .glyphicon-triangle-top:before { content: "\e253"; } .glyphicon-console:before { content: "\e254"; } .glyphicon-superscript:before { content: "\e255"; } .glyphicon-subscript:before { content: "\e256"; } .glyphicon-menu-left:before { content: "\e257"; } .glyphicon-menu-right:before { content: "\e258"; } .glyphicon-menu-down:before { content: "\e259"; } .glyphicon-menu-up:before { content: "\e260"; } * { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } *:before, *:after { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } html { font-size: 10px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } body { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 14px; line-height: 1.42857143; color: #333333; background-color: #fff; } input, button, select, textarea { font-family: inherit; font-size: inherit; line-height: inherit; } a { color: #337ab7; text-decoration: none; } a:hover, a:focus { color: #23527c; text-decoration: underline; } a:focus { outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; } figure { margin: 0; } img { vertical-align: middle; } .img-responsive, .thumbnail > img, .thumbnail a > img, .carousel-inner > .item > img, .carousel-inner > .item > a > img { display: block; max-width: 100%; height: auto; } .img-rounded { border-radius: 6px; } .img-thumbnail { padding: 4px; line-height: 1.42857143; background-color: #fff; border: 1px solid #ddd; border-radius: 4px; -webkit-transition: all 0.2s ease-in-out; -o-transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out; display: inline-block; max-width: 100%; height: auto; } .img-circle { border-radius: 50%; } hr { margin-top: 20px; margin-bottom: 20px; border: 0; border-top: 1px solid #eeeeee; } .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); border: 0; } .sr-only-focusable:active, .sr-only-focusable:focus { position: static; width: auto; height: auto; margin: 0; overflow: visible; clip: auto; } [role="button"] { cursor: pointer; } h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 { font-family: inherit; font-weight: 500; line-height: 1.1; color: inherit; } h1 small, h2 small, h3 small, h4 small, h5 small, h6 small, .h1 small, .h2 small, .h3 small, .h4 small, .h5 small, .h6 small, h1 .small, h2 .small, h3 .small, h4 .small, h5 .small, h6 .small, .h1 .small, .h2 .small, .h3 .small, .h4 .small, .h5 .small, .h6 .small { font-weight: 400; line-height: 1; color: #777777; } h1, .h1, h2, .h2, h3, .h3 { margin-top: 20px; margin-bottom: 10px; } h1 small, .h1 small, h2 small, .h2 small, h3 small, .h3 small, h1 .small, .h1 .small, h2 .small, .h2 .small, h3 .small, .h3 .small { font-size: 65%; } h4, .h4, h5, .h5, h6, .h6 { margin-top: 10px; margin-bottom: 10px; } h4 small, .h4 small, h5 small, .h5 small, h6 small, .h6 small, h4 .small, .h4 .small, h5 .small, .h5 .small, h6 .small, .h6 .small { font-size: 75%; } h1, .h1 { font-size: 36px; } h2, .h2 { font-size: 30px; } h3, .h3 { font-size: 24px; } h4, .h4 { font-size: 18px; } h5, .h5 { font-size: 14px; } h6, .h6 { font-size: 12px; } p { margin: 0 0 10px; } .lead { margin-bottom: 20px; font-size: 16px; font-weight: 300; line-height: 1.4; } @media (min-width: 768px) { .lead { font-size: 21px; } } small, .small { font-size: 85%; } mark, .mark { padding: 0.2em; background-color: #fcf8e3; } .text-left { text-align: left; } .text-right { text-align: right; } .text-center { text-align: center; } .text-justify { text-align: justify; } .text-nowrap { white-space: nowrap; } .text-lowercase { text-transform: lowercase; } .text-uppercase { text-transform: uppercase; } .text-capitalize { text-transform: capitalize; } .text-muted { color: #777777; } .text-primary { color: #337ab7; } a.text-primary:hover, a.text-primary:focus { color: #286090; } .text-success { color: #3c763d; } a.text-success:hover, a.text-success:focus { color: #2b542c; } .text-info { color: #31708f; } a.text-info:hover, a.text-info:focus { color: #245269; } .text-warning { color: #8a6d3b; } a.text-warning:hover, a.text-warning:focus { color: #66512c; } .text-danger { color: #a94442; } a.text-danger:hover, a.text-danger:focus { color: #843534; } .bg-primary { color: #fff; background-color: #337ab7; } a.bg-primary:hover, a.bg-primary:focus { background-color: #286090; } .bg-success { background-color: #dff0d8; } a.bg-success:hover, a.bg-success:focus { background-color: #c1e2b3; } .bg-info { background-color: #d9edf7; } a.bg-info:hover, a.bg-info:focus { background-color: #afd9ee; } .bg-warning { background-color: #fcf8e3; } a.bg-warning:hover, a.bg-warning:focus { background-color: #f7ecb5; } .bg-danger { background-color: #f2dede; } a.bg-danger:hover, a.bg-danger:focus { background-color: #e4b9b9; } .page-header { padding-bottom: 9px; margin: 40px 0 20px; border-bottom: 1px solid #eeeeee; } ul, ol { margin-top: 0; margin-bottom: 10px; } ul ul, ol ul, ul ol, ol ol { margin-bottom: 0; } .list-unstyled { padding-left: 0; list-style: none; } .list-inline { padding-left: 0; list-style: none; margin-left: -5px; } .list-inline > li { display: inline-block; padding-right: 5px; padding-left: 5px; } dl { margin-top: 0; margin-bottom: 20px; } dt, dd { line-height: 1.42857143; } dt { font-weight: 700; } dd { margin-left: 0; } @media (min-width: 768px) { .dl-horizontal dt { float: left; width: 160px; clear: left; text-align: right; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .dl-horizontal dd { margin-left: 180px; } } abbr[title], abbr[data-original-title] { cursor: help; } .initialism { font-size: 90%; text-transform: uppercase; } blockquote { padding: 10px 20px; margin: 0 0 20px; font-size: 17.5px; border-left: 5px solid #eeeeee; } blockquote p:last-child, blockquote ul:last-child, blockquote ol:last-child { margin-bottom: 0; } blockquote footer, blockquote small, blockquote .small { display: block; font-size: 80%; line-height: 1.42857143; color: #777777; } blockquote footer:before, blockquote small:before, blockquote .small:before { content: "\2014 \00A0"; } .blockquote-reverse, blockquote.pull-right { padding-right: 15px; padding-left: 0; text-align: right; border-right: 5px solid #eeeeee; border-left: 0; } .blockquote-reverse footer:before, blockquote.pull-right footer:before, .blockquote-reverse small:before, blockquote.pull-right small:before, .blockquote-reverse .small:before, blockquote.pull-right .small:before { content: ""; } .blockquote-reverse footer:after, blockquote.pull-right footer:after, .blockquote-reverse small:after, blockquote.pull-right small:after, .blockquote-reverse .small:after, blockquote.pull-right .small:after { content: "\00A0 \2014"; } address { margin-bottom: 20px; font-style: normal; line-height: 1.42857143; } code, kbd, pre, samp { font-family: Menlo, Monaco, Consolas, "Courier New", monospace; } code { padding: 2px 4px; font-size: 90%; color: #c7254e; background-color: #f9f2f4; border-radius: 4px; } kbd { padding: 2px 4px; font-size: 90%; color: #fff; background-color: #333; border-radius: 3px; -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); } kbd kbd { padding: 0; font-size: 100%; font-weight: 700; -webkit-box-shadow: none; box-shadow: none; } pre { display: block; padding: 9.5px; margin: 0 0 10px; font-size: 13px; line-height: 1.42857143; color: #333333; word-break: break-all; word-wrap: break-word; background-color: #f5f5f5; border: 1px solid #ccc; border-radius: 4px; } pre code { padding: 0; font-size: inherit; color: inherit; white-space: pre-wrap; background-color: transparent; border-radius: 0; } .pre-scrollable { max-height: 340px; overflow-y: scroll; } .container { padding-right: 15px; padding-left: 15px; margin-right: auto; margin-left: auto; } @media (min-width: 768px) { .container { width: 750px; } } @media (min-width: 992px) { .container { width: 970px; } } @media (min-width: 1200px) { .container { width: 1170px; } } .container-fluid { padding-right: 15px; padding-left: 15px; margin-right: auto; margin-left: auto; } .row { margin-right: -15px; margin-left: -15px; } .row-no-gutters { margin-right: 0; margin-left: 0; } .row-no-gutters [class*="col-"] { padding-right: 0; padding-left: 0; } .col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { position: relative; min-height: 1px; padding-right: 15px; padding-left: 15px; } .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { float: left; } .col-xs-12 { width: 100%; } .col-xs-11 { width: 91.66666667%; } .col-xs-10 { width: 83.33333333%; } .col-xs-9 { width: 75%; } .col-xs-8 { width: 66.66666667%; } .col-xs-7 { width: 58.33333333%; } .col-xs-6 { width: 50%; } .col-xs-5 { width: 41.66666667%; } .col-xs-4 { width: 33.33333333%; } .col-xs-3 { width: 25%; } .col-xs-2 { width: 16.66666667%; } .col-xs-1 { width: 8.33333333%; } .col-xs-pull-12 { right: 100%; } .col-xs-pull-11 { right: 91.66666667%; } .col-xs-pull-10 { right: 83.33333333%; } .col-xs-pull-9 { right: 75%; } .col-xs-pull-8 { right: 66.66666667%; } .col-xs-pull-7 { right: 58.33333333%; } .col-xs-pull-6 { right: 50%; } .col-xs-pull-5 { right: 41.66666667%; } .col-xs-pull-4 { right: 33.33333333%; } .col-xs-pull-3 { right: 25%; } .col-xs-pull-2 { right: 16.66666667%; } .col-xs-pull-1 { right: 8.33333333%; } .col-xs-pull-0 { right: auto; } .col-xs-push-12 { left: 100%; } .col-xs-push-11 { left: 91.66666667%; } .col-xs-push-10 { left: 83.33333333%; } .col-xs-push-9 { left: 75%; } .col-xs-push-8 { left: 66.66666667%; } .col-xs-push-7 { left: 58.33333333%; } .col-xs-push-6 { left: 50%; } .col-xs-push-5 { left: 41.66666667%; } .col-xs-push-4 { left: 33.33333333%; } .col-xs-push-3 { left: 25%; } .col-xs-push-2 { left: 16.66666667%; } .col-xs-push-1 { left: 8.33333333%; } .col-xs-push-0 { left: auto; } .col-xs-offset-12 { margin-left: 100%; } .col-xs-offset-11 { margin-left: 91.66666667%; } .col-xs-offset-10 { margin-left: 83.33333333%; } .col-xs-offset-9 { margin-left: 75%; } .col-xs-offset-8 { margin-left: 66.66666667%; } .col-xs-offset-7 { margin-left: 58.33333333%; } .col-xs-offset-6 { margin-left: 50%; } .col-xs-offset-5 { margin-left: 41.66666667%; } .col-xs-offset-4 { margin-left: 33.33333333%; } .col-xs-offset-3 { margin-left: 25%; } .col-xs-offset-2 { margin-left: 16.66666667%; } .col-xs-offset-1 { margin-left: 8.33333333%; } .col-xs-offset-0 { margin-left: 0%; } @media (min-width: 768px) { .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { float: left; } .col-sm-12 { width: 100%; } .col-sm-11 { width: 91.66666667%; } .col-sm-10 { width: 83.33333333%; } .col-sm-9 { width: 75%; } .col-sm-8 { width: 66.66666667%; } .col-sm-7 { width: 58.33333333%; } .col-sm-6 { width: 50%; } .col-sm-5 { width: 41.66666667%; } .col-sm-4 { width: 33.33333333%; } .col-sm-3 { width: 25%; } .col-sm-2 { width: 16.66666667%; } .col-sm-1 { width: 8.33333333%; } .col-sm-pull-12 { right: 100%; } .col-sm-pull-11 { right: 91.66666667%; } .col-sm-pull-10 { right: 83.33333333%; } .col-sm-pull-9 { right: 75%; } .col-sm-pull-8 { right: 66.66666667%; } .col-sm-pull-7 { right: 58.33333333%; } .col-sm-pull-6 { right: 50%; } .col-sm-pull-5 { right: 41.66666667%; } .col-sm-pull-4 { right: 33.33333333%; } .col-sm-pull-3 { right: 25%; } .col-sm-pull-2 { right: 16.66666667%; } .col-sm-pull-1 { right: 8.33333333%; } .col-sm-pull-0 { right: auto; } .col-sm-push-12 { left: 100%; } .col-sm-push-11 { left: 91.66666667%; } .col-sm-push-10 { left: 83.33333333%; } .col-sm-push-9 { left: 75%; } .col-sm-push-8 { left: 66.66666667%; } .col-sm-push-7 { left: 58.33333333%; } .col-sm-push-6 { left: 50%; } .col-sm-push-5 { left: 41.66666667%; } .col-sm-push-4 { left: 33.33333333%; } .col-sm-push-3 { left: 25%; } .col-sm-push-2 { left: 16.66666667%; } .col-sm-push-1 { left: 8.33333333%; } .col-sm-push-0 { left: auto; } .col-sm-offset-12 { margin-left: 100%; } .col-sm-offset-11 { margin-left: 91.66666667%; } .col-sm-offset-10 { margin-left: 83.33333333%; } .col-sm-offset-9 { margin-left: 75%; } .col-sm-offset-8 { margin-left: 66.66666667%; } .col-sm-offset-7 { margin-left: 58.33333333%; } .col-sm-offset-6 { margin-left: 50%; } .col-sm-offset-5 { margin-left: 41.66666667%; } .col-sm-offset-4 { margin-left: 33.33333333%; } .col-sm-offset-3 { margin-left: 25%; } .col-sm-offset-2 { margin-left: 16.66666667%; } .col-sm-offset-1 { margin-left: 8.33333333%; } .col-sm-offset-0 { margin-left: 0%; } } @media (min-width: 992px) { .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { float: left; } .col-md-12 { width: 100%; } .col-md-11 { width: 91.66666667%; } .col-md-10 { width: 83.33333333%; } .col-md-9 { width: 75%; } .col-md-8 { width: 66.66666667%; } .col-md-7 { width: 58.33333333%; } .col-md-6 { width: 50%; } .col-md-5 { width: 41.66666667%; } .col-md-4 { width: 33.33333333%; } .col-md-3 { width: 25%; } .col-md-2 { width: 16.66666667%; } .col-md-1 { width: 8.33333333%; } .col-md-pull-12 { right: 100%; } .col-md-pull-11 { right: 91.66666667%; } .col-md-pull-10 { right: 83.33333333%; } .col-md-pull-9 { right: 75%; } .col-md-pull-8 { right: 66.66666667%; } .col-md-pull-7 { right: 58.33333333%; } .col-md-pull-6 { right: 50%; } .col-md-pull-5 { right: 41.66666667%; } .col-md-pull-4 { right: 33.33333333%; } .col-md-pull-3 { right: 25%; } .col-md-pull-2 { right: 16.66666667%; } .col-md-pull-1 { right: 8.33333333%; } .col-md-pull-0 { right: auto; } .col-md-push-12 { left: 100%; } .col-md-push-11 { left: 91.66666667%; } .col-md-push-10 { left: 83.33333333%; } .col-md-push-9 { left: 75%; } .col-md-push-8 { left: 66.66666667%; } .col-md-push-7 { left: 58.33333333%; } .col-md-push-6 { left: 50%; } .col-md-push-5 { left: 41.66666667%; } .col-md-push-4 { left: 33.33333333%; } .col-md-push-3 { left: 25%; } .col-md-push-2 { left: 16.66666667%; } .col-md-push-1 { left: 8.33333333%; } .col-md-push-0 { left: auto; } .col-md-offset-12 { margin-left: 100%; } .col-md-offset-11 { margin-left: 91.66666667%; } .col-md-offset-10 { margin-left: 83.33333333%; } .col-md-offset-9 { margin-left: 75%; } .col-md-offset-8 { margin-left: 66.66666667%; } .col-md-offset-7 { margin-left: 58.33333333%; } .col-md-offset-6 { margin-left: 50%; } .col-md-offset-5 { margin-left: 41.66666667%; } .col-md-offset-4 { margin-left: 33.33333333%; } .col-md-offset-3 { margin-left: 25%; } .col-md-offset-2 { margin-left: 16.66666667%; } .col-md-offset-1 { margin-left: 8.33333333%; } .col-md-offset-0 { margin-left: 0%; } } @media (min-width: 1200px) { .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { float: left; } .col-lg-12 { width: 100%; } .col-lg-11 { width: 91.66666667%; } .col-lg-10 { width: 83.33333333%; } .col-lg-9 { width: 75%; } .col-lg-8 { width: 66.66666667%; } .col-lg-7 { width: 58.33333333%; } .col-lg-6 { width: 50%; } .col-lg-5 { width: 41.66666667%; } .col-lg-4 { width: 33.33333333%; } .col-lg-3 { width: 25%; } .col-lg-2 { width: 16.66666667%; } .col-lg-1 { width: 8.33333333%; } .col-lg-pull-12 { right: 100%; } .col-lg-pull-11 { right: 91.66666667%; } .col-lg-pull-10 { right: 83.33333333%; } .col-lg-pull-9 { right: 75%; } .col-lg-pull-8 { right: 66.66666667%; } .col-lg-pull-7 { right: 58.33333333%; } .col-lg-pull-6 { right: 50%; } .col-lg-pull-5 { right: 41.66666667%; } .col-lg-pull-4 { right: 33.33333333%; } .col-lg-pull-3 { right: 25%; } .col-lg-pull-2 { right: 16.66666667%; } .col-lg-pull-1 { right: 8.33333333%; } .col-lg-pull-0 { right: auto; } .col-lg-push-12 { left: 100%; } .col-lg-push-11 { left: 91.66666667%; } .col-lg-push-10 { left: 83.33333333%; } .col-lg-push-9 { left: 75%; } .col-lg-push-8 { left: 66.66666667%; } .col-lg-push-7 { left: 58.33333333%; } .col-lg-push-6 { left: 50%; } .col-lg-push-5 { left: 41.66666667%; } .col-lg-push-4 { left: 33.33333333%; } .col-lg-push-3 { left: 25%; } .col-lg-push-2 { left: 16.66666667%; } .col-lg-push-1 { left: 8.33333333%; } .col-lg-push-0 { left: auto; } .col-lg-offset-12 { margin-left: 100%; } .col-lg-offset-11 { margin-left: 91.66666667%; } .col-lg-offset-10 { margin-left: 83.33333333%; } .col-lg-offset-9 { margin-left: 75%; } .col-lg-offset-8 { margin-left: 66.66666667%; } .col-lg-offset-7 { margin-left: 58.33333333%; } .col-lg-offset-6 { margin-left: 50%; } .col-lg-offset-5 { margin-left: 41.66666667%; } .col-lg-offset-4 { margin-left: 33.33333333%; } .col-lg-offset-3 { margin-left: 25%; } .col-lg-offset-2 { margin-left: 16.66666667%; } .col-lg-offset-1 { margin-left: 8.33333333%; } .col-lg-offset-0 { margin-left: 0%; } } table { background-color: transparent; } table col[class*="col-"] { position: static; display: table-column; float: none; } table td[class*="col-"], table th[class*="col-"] { position: static; display: table-cell; float: none; } caption { padding-top: 8px; padding-bottom: 8px; color: #777777; text-align: left; } th { text-align: left; } .table { width: 100%; max-width: 100%; margin-bottom: 20px; } .table > thead > tr > th, .table > tbody > tr > th, .table > tfoot > tr > th, .table > thead > tr > td, .table > tbody > tr > td, .table > tfoot > tr > td { padding: 8px; line-height: 1.42857143; vertical-align: top; border-top: 1px solid #ddd; } .table > thead > tr > th { vertical-align: bottom; border-bottom: 2px solid #ddd; } .table > caption + thead > tr:first-child > th, .table > colgroup + thead > tr:first-child > th, .table > thead:first-child > tr:first-child > th, .table > caption + thead > tr:first-child > td, .table > colgroup + thead > tr:first-child > td, .table > thead:first-child > tr:first-child > td { border-top: 0; } .table > tbody + tbody { border-top: 2px solid #ddd; } .table .table { background-color: #fff; } .table-condensed > thead > tr > th, .table-condensed > tbody > tr > th, .table-condensed > tfoot > tr > th, .table-condensed > thead > tr > td, .table-condensed > tbody > tr > td, .table-condensed > tfoot > tr > td { padding: 5px; } .table-bordered { border: 1px solid #ddd; } .table-bordered > thead > tr > th, .table-bordered > tbody > tr > th, .table-bordered > tfoot > tr > th, .table-bordered > thead > tr > td, .table-bordered > tbody > tr > td, .table-bordered > tfoot > tr > td { border: 1px solid #ddd; } .table-bordered > thead > tr > th, .table-bordered > thead > tr > td { border-bottom-width: 2px; } .table-striped > tbody > tr:nth-of-type(odd) { background-color: #f9f9f9; } .table-hover > tbody > tr:hover { background-color: #f5f5f5; } .table > thead > tr > td.active, .table > tbody > tr > td.active, .table > tfoot > tr > td.active, .table > thead > tr > th.active, .table > tbody > tr > th.active, .table > tfoot > tr > th.active, .table > thead > tr.active > td, .table > tbody > tr.active > td, .table > tfoot > tr.active > td, .table > thead > tr.active > th, .table > tbody > tr.active > th, .table > tfoot > tr.active > th { background-color: #f5f5f5; } .table-hover > tbody > tr > td.active:hover, .table-hover > tbody > tr > th.active:hover, .table-hover > tbody > tr.active:hover > td, .table-hover > tbody > tr:hover > .active, .table-hover > tbody > tr.active:hover > th { background-color: #e8e8e8; } .table > thead > tr > td.success, .table > tbody > tr > td.success, .table > tfoot > tr > td.success, .table > thead > tr > th.success, .table > tbody > tr > th.success, .table > tfoot > tr > th.success, .table > thead > tr.success > td, .table > tbody > tr.success > td, .table > tfoot > tr.success > td, .table > thead > tr.success > th, .table > tbody > tr.success > th, .table > tfoot > tr.success > th { background-color: #dff0d8; } .table-hover > tbody > tr > td.success:hover, .table-hover > tbody > tr > th.success:hover, .table-hover > tbody > tr.success:hover > td, .table-hover > tbody > tr:hover > .success, .table-hover > tbody > tr.success:hover > th { background-color: #d0e9c6; } .table > thead > tr > td.info, .table > tbody > tr > td.info, .table > tfoot > tr > td.info, .table > thead > tr > th.info, .table > tbody > tr > th.info, .table > tfoot > tr > th.info, .table > thead > tr.info > td, .table > tbody > tr.info > td, .table > tfoot > tr.info > td, .table > thead > tr.info > th, .table > tbody > tr.info > th, .table > tfoot > tr.info > th { background-color: #d9edf7; } .table-hover > tbody > tr > td.info:hover, .table-hover > tbody > tr > th.info:hover, .table-hover > tbody > tr.info:hover > td, .table-hover > tbody > tr:hover > .info, .table-hover > tbody > tr.info:hover > th { background-color: #c4e3f3; } .table > thead > tr > td.warning, .table > tbody > tr > td.warning, .table > tfoot > tr > td.warning, .table > thead > tr > th.warning, .table > tbody > tr > th.warning, .table > tfoot > tr > th.warning, .table > thead > tr.warning > td, .table > tbody > tr.warning > td, .table > tfoot > tr.warning > td, .table > thead > tr.warning > th, .table > tbody > tr.warning > th, .table > tfoot > tr.warning > th { background-color: #fcf8e3; } .table-hover > tbody > tr > td.warning:hover, .table-hover > tbody > tr > th.warning:hover, .table-hover > tbody > tr.warning:hover > td, .table-hover > tbody > tr:hover > .warning, .table-hover > tbody > tr.warning:hover > th { background-color: #faf2cc; } .table > thead > tr > td.danger, .table > tbody > tr > td.danger, .table > tfoot > tr > td.danger, .table > thead > tr > th.danger, .table > tbody > tr > th.danger, .table > tfoot > tr > th.danger, .table > thead > tr.danger > td, .table > tbody > tr.danger > td, .table > tfoot > tr.danger > td, .table > thead > tr.danger > th, .table > tbody > tr.danger > th, .table > tfoot > tr.danger > th { background-color: #f2dede; } .table-hover > tbody > tr > td.danger:hover, .table-hover > tbody > tr > th.danger:hover, .table-hover > tbody > tr.danger:hover > td, .table-hover > tbody > tr:hover > .danger, .table-hover > tbody > tr.danger:hover > th { background-color: #ebcccc; } .table-responsive { min-height: 0.01%; overflow-x: auto; } @media screen and (max-width: 767px) { .table-responsive { width: 100%; margin-bottom: 15px; overflow-y: hidden; -ms-overflow-style: -ms-autohiding-scrollbar; border: 1px solid #ddd; } .table-responsive > .table { margin-bottom: 0; } .table-responsive > .table > thead > tr > th, .table-responsive > .table > tbody > tr > th, .table-responsive > .table > tfoot > tr > th, .table-responsive > .table > thead > tr > td, .table-responsive > .table > tbody > tr > td, .table-responsive > .table > tfoot > tr > td { white-space: nowrap; } .table-responsive > .table-bordered { border: 0; } .table-responsive > .table-bordered > thead > tr > th:first-child, .table-responsive > .table-bordered > tbody > tr > th:first-child, .table-responsive > .table-bordered > tfoot > tr > th:first-child, .table-responsive > .table-bordered > thead > tr > td:first-child, .table-responsive > .table-bordered > tbody > tr > td:first-child, .table-responsive > .table-bordered > tfoot > tr > td:first-child { border-left: 0; } .table-responsive > .table-bordered > thead > tr > th:last-child, .table-responsive > .table-bordered > tbody > tr > th:last-child, .table-responsive > .table-bordered > tfoot > tr > th:last-child, .table-responsive > .table-bordered > thead > tr > td:last-child, .table-responsive > .table-bordered > tbody > tr > td:last-child, .table-responsive > .table-bordered > tfoot > tr > td:last-child { border-right: 0; } .table-responsive > .table-bordered > tbody > tr:last-child > th, .table-responsive > .table-bordered > tfoot > tr:last-child > th, .table-responsive > .table-bordered > tbody > tr:last-child > td, .table-responsive > .table-bordered > tfoot > tr:last-child > td { border-bottom: 0; } } fieldset { min-width: 0; padding: 0; margin: 0; border: 0; } legend { display: block; width: 100%; padding: 0; margin-bottom: 20px; font-size: 21px; line-height: inherit; color: #333333; border: 0; border-bottom: 1px solid #e5e5e5; } label { display: inline-block; max-width: 100%; margin-bottom: 5px; font-weight: 700; } input[type="search"] { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; -webkit-appearance: none; -moz-appearance: none; appearance: none; } input[type="radio"], input[type="checkbox"] { margin: 4px 0 0; margin-top: 1px \9; line-height: normal; } input[type="radio"][disabled], input[type="checkbox"][disabled], input[type="radio"].disabled, input[type="checkbox"].disabled, fieldset[disabled] input[type="radio"], fieldset[disabled] input[type="checkbox"] { cursor: not-allowed; } input[type="file"] { display: block; } input[type="range"] { display: block; width: 100%; } select[multiple], select[size] { height: auto; } input[type="file"]:focus, input[type="radio"]:focus, input[type="checkbox"]:focus { outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; } output { display: block; padding-top: 7px; font-size: 14px; line-height: 1.42857143; color: #555555; } .form-control { display: block; width: 100%; height: 34px; padding: 6px 12px; font-size: 14px; line-height: 1.42857143; color: #555555; background-color: #fff; background-image: none; border: 1px solid #ccc; border-radius: 4px; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; } .form-control:focus { border-color: #66afe9; outline: 0; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, 0.6); box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, 0.6); } .form-control::-moz-placeholder { color: #999; opacity: 1; } .form-control:-ms-input-placeholder { color: #999; } .form-control::-webkit-input-placeholder { color: #999; } .form-control::-ms-expand { background-color: transparent; border: 0; } .form-control[disabled], .form-control[readonly], fieldset[disabled] .form-control { background-color: #eeeeee; opacity: 1; } .form-control[disabled], fieldset[disabled] .form-control { cursor: not-allowed; } textarea.form-control { height: auto; } @media screen and (-webkit-min-device-pixel-ratio: 0) { input[type="date"].form-control, input[type="time"].form-control, input[type="datetime-local"].form-control, input[type="month"].form-control { line-height: 34px; } input[type="date"].input-sm, input[type="time"].input-sm, input[type="datetime-local"].input-sm, input[type="month"].input-sm, .input-group-sm input[type="date"], .input-group-sm input[type="time"], .input-group-sm input[type="datetime-local"], .input-group-sm input[type="month"] { line-height: 30px; } input[type="date"].input-lg, input[type="time"].input-lg, input[type="datetime-local"].input-lg, input[type="month"].input-lg, .input-group-lg input[type="date"], .input-group-lg input[type="time"], .input-group-lg input[type="datetime-local"], .input-group-lg input[type="month"] { line-height: 46px; } } .form-group { margin-bottom: 15px; } .radio, .checkbox { position: relative; display: block; margin-top: 10px; margin-bottom: 10px; } .radio.disabled label, .checkbox.disabled label, fieldset[disabled] .radio label, fieldset[disabled] .checkbox label { cursor: not-allowed; } .radio label, .checkbox label { min-height: 20px; padding-left: 20px; margin-bottom: 0; font-weight: 400; cursor: pointer; } .radio input[type="radio"], .radio-inline input[type="radio"], .checkbox input[type="checkbox"], .checkbox-inline input[type="checkbox"] { position: absolute; margin-top: 4px \9; margin-left: -20px; } .radio + .radio, .checkbox + .checkbox { margin-top: -5px; } .radio-inline, .checkbox-inline { position: relative; display: inline-block; padding-left: 20px; margin-bottom: 0; font-weight: 400; vertical-align: middle; cursor: pointer; } .radio-inline.disabled, .checkbox-inline.disabled, fieldset[disabled] .radio-inline, fieldset[disabled] .checkbox-inline { cursor: not-allowed; } .radio-inline + .radio-inline, .checkbox-inline + .checkbox-inline { margin-top: 0; margin-left: 10px; } .form-control-static { min-height: 34px; padding-top: 7px; padding-bottom: 7px; margin-bottom: 0; } .form-control-static.input-lg, .form-control-static.input-sm { padding-right: 0; padding-left: 0; } .input-sm { height: 30px; padding: 5px 10px; font-size: 12px; line-height: 1.5; border-radius: 3px; } select.input-sm { height: 30px; line-height: 30px; } textarea.input-sm, select[multiple].input-sm { height: auto; } .form-group-sm .form-control { height: 30px; padding: 5px 10px; font-size: 12px; line-height: 1.5; border-radius: 3px; } .form-group-sm select.form-control { height: 30px; line-height: 30px; } .form-group-sm textarea.form-control, .form-group-sm select[multiple].form-control { height: auto; } .form-group-sm .form-control-static { height: 30px; min-height: 32px; padding: 6px 10px; font-size: 12px; line-height: 1.5; } .input-lg { height: 46px; padding: 10px 16px; font-size: 18px; line-height: 1.3333333; border-radius: 6px; } select.input-lg { height: 46px; line-height: 46px; } textarea.input-lg, select[multiple].input-lg { height: auto; } .form-group-lg .form-control { height: 46px; padding: 10px 16px; font-size: 18px; line-height: 1.3333333; border-radius: 6px; } .form-group-lg select.form-control { height: 46px; line-height: 46px; } .form-group-lg textarea.form-control, .form-group-lg select[multiple].form-control { height: auto; } .form-group-lg .form-control-static { height: 46px; min-height: 38px; padding: 11px 16px; font-size: 18px; line-height: 1.3333333; } .has-feedback { position: relative; } .has-feedback .form-control { padding-right: 42.5px; } .form-control-feedback { position: absolute; top: 0; right: 0; z-index: 2; display: block; width: 34px; height: 34px; line-height: 34px; text-align: center; pointer-events: none; } .input-lg + .form-control-feedback, .input-group-lg + .form-control-feedback, .form-group-lg .form-control + .form-control-feedback { width: 46px; height: 46px; line-height: 46px; } .input-sm + .form-control-feedback, .input-group-sm + .form-control-feedback, .form-group-sm .form-control + .form-control-feedback { width: 30px; height: 30px; line-height: 30px; } .has-success .help-block, .has-success .control-label, .has-success .radio, .has-success .checkbox, .has-success .radio-inline, .has-success .checkbox-inline, .has-success.radio label, .has-success.checkbox label, .has-success.radio-inline label, .has-success.checkbox-inline label { color: #3c763d; } .has-success .form-control { border-color: #3c763d; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); } .has-success .form-control:focus { border-color: #2b542c; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; } .has-success .input-group-addon { color: #3c763d; background-color: #dff0d8; border-color: #3c763d; } .has-success .form-control-feedback { color: #3c763d; } .has-warning .help-block, .has-warning .control-label, .has-warning .radio, .has-warning .checkbox, .has-warning .radio-inline, .has-warning .checkbox-inline, .has-warning.radio label, .has-warning.checkbox label, .has-warning.radio-inline label, .has-warning.checkbox-inline label { color: #8a6d3b; } .has-warning .form-control { border-color: #8a6d3b; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); } .has-warning .form-control:focus { border-color: #66512c; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; } .has-warning .input-group-addon { color: #8a6d3b; background-color: #fcf8e3; border-color: #8a6d3b; } .has-warning .form-control-feedback { color: #8a6d3b; } .has-error .help-block, .has-error .control-label, .has-error .radio, .has-error .checkbox, .has-error .radio-inline, .has-error .checkbox-inline, .has-error.radio label, .has-error.checkbox label, .has-error.radio-inline label, .has-error.checkbox-inline label { color: #a94442; } .has-error .form-control { border-color: #a94442; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); } .has-error .form-control:focus { border-color: #843534; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; } .has-error .input-group-addon { color: #a94442; background-color: #f2dede; border-color: #a94442; } .has-error .form-control-feedback { color: #a94442; } .has-feedback label ~ .form-control-feedback { top: 25px; } .has-feedback label.sr-only ~ .form-control-feedback { top: 0; } .help-block { display: block; margin-top: 5px; margin-bottom: 10px; color: #737373; } @media (min-width: 768px) { .form-inline .form-group { display: inline-block; margin-bottom: 0; vertical-align: middle; } .form-inline .form-control { display: inline-block; width: auto; vertical-align: middle; } .form-inline .form-control-static { display: inline-block; } .form-inline .input-group { display: inline-table; vertical-align: middle; } .form-inline .input-group .input-group-addon, .form-inline .input-group .input-group-btn, .form-inline .input-group .form-control { width: auto; } .form-inline .input-group > .form-control { width: 100%; } .form-inline .control-label { margin-bottom: 0; vertical-align: middle; } .form-inline .radio, .form-inline .checkbox { display: inline-block; margin-top: 0; margin-bottom: 0; vertical-align: middle; } .form-inline .radio label, .form-inline .checkbox label { padding-left: 0; } .form-inline .radio input[type="radio"], .form-inline .checkbox input[type="checkbox"] { position: relative; margin-left: 0; } .form-inline .has-feedback .form-control-feedback { top: 0; } } .form-horizontal .radio, .form-horizontal .checkbox, .form-horizontal .radio-inline, .form-horizontal .checkbox-inline { padding-top: 7px; margin-top: 0; margin-bottom: 0; } .form-horizontal .radio, .form-horizontal .checkbox { min-height: 27px; } .form-horizontal .form-group { margin-right: -15px; margin-left: -15px; } @media (min-width: 768px) { .form-horizontal .control-label { padding-top: 7px; margin-bottom: 0; text-align: right; } } .form-horizontal .has-feedback .form-control-feedback { right: 15px; } @media (min-width: 768px) { .form-horizontal .form-group-lg .control-label { padding-top: 11px; font-size: 18px; } } @media (min-width: 768px) { .form-horizontal .form-group-sm .control-label { padding-top: 6px; font-size: 12px; } } .btn { display: inline-block; margin-bottom: 0; font-weight: normal; text-align: center; white-space: nowrap; vertical-align: middle; -ms-touch-action: manipulation; touch-action: manipulation; cursor: pointer; background-image: none; border: 1px solid transparent; padding: 6px 12px; font-size: 14px; line-height: 1.42857143; border-radius: 4px; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .btn:focus, .btn:active:focus, .btn.active:focus, .btn.focus, .btn:active.focus, .btn.active.focus { outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; } .btn:hover, .btn:focus, .btn.focus { color: #333; text-decoration: none; } .btn:active, .btn.active { background-image: none; outline: 0; -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); } .btn.disabled, .btn[disabled], fieldset[disabled] .btn { cursor: not-allowed; filter: alpha(opacity=65); opacity: 0.65; -webkit-box-shadow: none; box-shadow: none; } a.btn.disabled, fieldset[disabled] a.btn { pointer-events: none; } .btn-default { color: #333; background-color: #fff; border-color: #ccc; } .btn-default:focus, .btn-default.focus { color: #333; background-color: #e6e6e6; border-color: #8c8c8c; } .btn-default:hover { color: #333; background-color: #e6e6e6; border-color: #adadad; } .btn-default:active, .btn-default.active, .open > .dropdown-toggle.btn-default { color: #333; background-color: #e6e6e6; background-image: none; border-color: #adadad; } .btn-default:active:hover, .btn-default.active:hover, .open > .dropdown-toggle.btn-default:hover, .btn-default:active:focus, .btn-default.active:focus, .open > .dropdown-toggle.btn-default:focus, .btn-default:active.focus, .btn-default.active.focus, .open > .dropdown-toggle.btn-default.focus { color: #333; background-color: #d4d4d4; border-color: #8c8c8c; } .btn-default.disabled:hover, .btn-default[disabled]:hover, fieldset[disabled] .btn-default:hover, .btn-default.disabled:focus, .btn-default[disabled]:focus, fieldset[disabled] .btn-default:focus, .btn-default.disabled.focus, .btn-default[disabled].focus, fieldset[disabled] .btn-default.focus { background-color: #fff; border-color: #ccc; } .btn-default .badge { color: #fff; background-color: #333; } .btn-primary { color: #fff; background-color: #337ab7; border-color: #2e6da4; } .btn-primary:focus, .btn-primary.focus { color: #fff; background-color: #286090; border-color: #122b40; } .btn-primary:hover { color: #fff; background-color: #286090; border-color: #204d74; } .btn-primary:active, .btn-primary.active, .open > .dropdown-toggle.btn-primary { color: #fff; background-color: #286090; background-image: none; border-color: #204d74; } .btn-primary:active:hover, .btn-primary.active:hover, .open > .dropdown-toggle.btn-primary:hover, .btn-primary:active:focus, .btn-primary.active:focus, .open > .dropdown-toggle.btn-primary:focus, .btn-primary:active.focus, .btn-primary.active.focus, .open > .dropdown-toggle.btn-primary.focus { color: #fff; background-color: #204d74; border-color: #122b40; } .btn-primary.disabled:hover, .btn-primary[disabled]:hover, fieldset[disabled] .btn-primary:hover, .btn-primary.disabled:focus, .btn-primary[disabled]:focus, fieldset[disabled] .btn-primary:focus, .btn-primary.disabled.focus, .btn-primary[disabled].focus, fieldset[disabled] .btn-primary.focus { background-color: #337ab7; border-color: #2e6da4; } .btn-primary .badge { color: #337ab7; background-color: #fff; } .btn-success { color: #fff; background-color: #5cb85c; border-color: #4cae4c; } .btn-success:focus, .btn-success.focus { color: #fff; background-color: #449d44; border-color: #255625; } .btn-success:hover { color: #fff; background-color: #449d44; border-color: #398439; } .btn-success:active, .btn-success.active, .open > .dropdown-toggle.btn-success { color: #fff; background-color: #449d44; background-image: none; border-color: #398439; } .btn-success:active:hover, .btn-success.active:hover, .open > .dropdown-toggle.btn-success:hover, .btn-success:active:focus, .btn-success.active:focus, .open > .dropdown-toggle.btn-success:focus, .btn-success:active.focus, .btn-success.active.focus, .open > .dropdown-toggle.btn-success.focus { color: #fff; background-color: #398439; border-color: #255625; } .btn-success.disabled:hover, .btn-success[disabled]:hover, fieldset[disabled] .btn-success:hover, .btn-success.disabled:focus, .btn-success[disabled]:focus, fieldset[disabled] .btn-success:focus, .btn-success.disabled.focus, .btn-success[disabled].focus, fieldset[disabled] .btn-success.focus { background-color: #5cb85c; border-color: #4cae4c; } .btn-success .badge { color: #5cb85c; background-color: #fff; } .btn-info { color: #fff; background-color: #5bc0de; border-color: #46b8da; } .btn-info:focus, .btn-info.focus { color: #fff; background-color: #31b0d5; border-color: #1b6d85; } .btn-info:hover { color: #fff; background-color: #31b0d5; border-color: #269abc; } .btn-info:active, .btn-info.active, .open > .dropdown-toggle.btn-info { color: #fff; background-color: #31b0d5; background-image: none; border-color: #269abc; } .btn-info:active:hover, .btn-info.active:hover, .open > .dropdown-toggle.btn-info:hover, .btn-info:active:focus, .btn-info.active:focus, .open > .dropdown-toggle.btn-info:focus, .btn-info:active.focus, .btn-info.active.focus, .open > .dropdown-toggle.btn-info.focus { color: #fff; background-color: #269abc; border-color: #1b6d85; } .btn-info.disabled:hover, .btn-info[disabled]:hover, fieldset[disabled] .btn-info:hover, .btn-info.disabled:focus, .btn-info[disabled]:focus, fieldset[disabled] .btn-info:focus, .btn-info.disabled.focus, .btn-info[disabled].focus, fieldset[disabled] .btn-info.focus { background-color: #5bc0de; border-color: #46b8da; } .btn-info .badge { color: #5bc0de; background-color: #fff; } .btn-warning { color: #fff; background-color: #f0ad4e; border-color: #eea236; } .btn-warning:focus, .btn-warning.focus { color: #fff; background-color: #ec971f; border-color: #985f0d; } .btn-warning:hover { color: #fff; background-color: #ec971f; border-color: #d58512; } .btn-warning:active, .btn-warning.active, .open > .dropdown-toggle.btn-warning { color: #fff; background-color: #ec971f; background-image: none; border-color: #d58512; } .btn-warning:active:hover, .btn-warning.active:hover, .open > .dropdown-toggle.btn-warning:hover, .btn-warning:active:focus, .btn-warning.active:focus, .open > .dropdown-toggle.btn-warning:focus, .btn-warning:active.focus, .btn-warning.active.focus, .open > .dropdown-toggle.btn-warning.focus { color: #fff; background-color: #d58512; border-color: #985f0d; } .btn-warning.disabled:hover, .btn-warning[disabled]:hover, fieldset[disabled] .btn-warning:hover, .btn-warning.disabled:focus, .btn-warning[disabled]:focus, fieldset[disabled] .btn-warning:focus, .btn-warning.disabled.focus, .btn-warning[disabled].focus, fieldset[disabled] .btn-warning.focus { background-color: #f0ad4e; border-color: #eea236; } .btn-warning .badge { color: #f0ad4e; background-color: #fff; } .btn-danger { color: #fff; background-color: #d9534f; border-color: #d43f3a; } .btn-danger:focus, .btn-danger.focus { color: #fff; background-color: #c9302c; border-color: #761c19; } .btn-danger:hover { color: #fff; background-color: #c9302c; border-color: #ac2925; } .btn-danger:active, .btn-danger.active, .open > .dropdown-toggle.btn-danger { color: #fff; background-color: #c9302c; background-image: none; border-color: #ac2925; } .btn-danger:active:hover, .btn-danger.active:hover, .open > .dropdown-toggle.btn-danger:hover, .btn-danger:active:focus, .btn-danger.active:focus, .open > .dropdown-toggle.btn-danger:focus, .btn-danger:active.focus, .btn-danger.active.focus, .open > .dropdown-toggle.btn-danger.focus { color: #fff; background-color: #ac2925; border-color: #761c19; } .btn-danger.disabled:hover, .btn-danger[disabled]:hover, fieldset[disabled] .btn-danger:hover, .btn-danger.disabled:focus, .btn-danger[disabled]:focus, fieldset[disabled] .btn-danger:focus, .btn-danger.disabled.focus, .btn-danger[disabled].focus, fieldset[disabled] .btn-danger.focus { background-color: #d9534f; border-color: #d43f3a; } .btn-danger .badge { color: #d9534f; background-color: #fff; } .btn-link { font-weight: 400; color: #337ab7; border-radius: 0; } .btn-link, .btn-link:active, .btn-link.active, .btn-link[disabled], fieldset[disabled] .btn-link { background-color: transparent; -webkit-box-shadow: none; box-shadow: none; } .btn-link, .btn-link:hover, .btn-link:focus, .btn-link:active { border-color: transparent; } .btn-link:hover, .btn-link:focus { color: #23527c; text-decoration: underline; background-color: transparent; } .btn-link[disabled]:hover, fieldset[disabled] .btn-link:hover, .btn-link[disabled]:focus, fieldset[disabled] .btn-link:focus { color: #777777; text-decoration: none; } .btn-lg, .btn-group-lg > .btn { padding: 10px 16px; font-size: 18px; line-height: 1.3333333; border-radius: 6px; } .btn-sm, .btn-group-sm > .btn { padding: 5px 10px; font-size: 12px; line-height: 1.5; border-radius: 3px; } .btn-xs, .btn-group-xs > .btn { padding: 1px 5px; font-size: 12px; line-height: 1.5; border-radius: 3px; } .btn-block { display: block; width: 100%; } .btn-block + .btn-block { margin-top: 5px; } input[type="submit"].btn-block, input[type="reset"].btn-block, input[type="button"].btn-block { width: 100%; } .fade { opacity: 0; -webkit-transition: opacity 0.15s linear; -o-transition: opacity 0.15s linear; transition: opacity 0.15s linear; } .fade.in { opacity: 1; } .collapse { display: none; } .collapse.in { display: block; } tr.collapse.in { display: table-row; } tbody.collapse.in { display: table-row-group; } .collapsing { position: relative; height: 0; overflow: hidden; -webkit-transition-property: height, visibility; -o-transition-property: height, visibility; transition-property: height, visibility; -webkit-transition-duration: 0.35s; -o-transition-duration: 0.35s; transition-duration: 0.35s; -webkit-transition-timing-function: ease; -o-transition-timing-function: ease; transition-timing-function: ease; } .caret { display: inline-block; width: 0; height: 0; margin-left: 2px; vertical-align: middle; border-top: 4px dashed; border-top: 4px solid \9; border-right: 4px solid transparent; border-left: 4px solid transparent; } .dropup, .dropdown { position: relative; } .dropdown-toggle:focus { outline: 0; } .dropdown-menu { position: absolute; top: 100%; left: 0; z-index: 1000; display: none; float: left; min-width: 160px; padding: 5px 0; margin: 2px 0 0; font-size: 14px; text-align: left; list-style: none; background-color: #fff; background-clip: padding-box; border: 1px solid #ccc; border: 1px solid rgba(0, 0, 0, 0.15); border-radius: 4px; -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); } .dropdown-menu.pull-right { right: 0; left: auto; } .dropdown-menu .divider { height: 1px; margin: 9px 0; overflow: hidden; background-color: #e5e5e5; } .dropdown-menu > li > a { display: block; padding: 3px 20px; clear: both; font-weight: 400; line-height: 1.42857143; color: #333333; white-space: nowrap; } .dropdown-menu > li > a:hover, .dropdown-menu > li > a:focus { color: #262626; text-decoration: none; background-color: #f5f5f5; } .dropdown-menu > .active > a, .dropdown-menu > .active > a:hover, .dropdown-menu > .active > a:focus { color: #fff; text-decoration: none; background-color: #337ab7; outline: 0; } .dropdown-menu > .disabled > a, .dropdown-menu > .disabled > a:hover, .dropdown-menu > .disabled > a:focus { color: #777777; } .dropdown-menu > .disabled > a:hover, .dropdown-menu > .disabled > a:focus { text-decoration: none; cursor: not-allowed; background-color: transparent; background-image: none; filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); } .open > .dropdown-menu { display: block; } .open > a { outline: 0; } .dropdown-menu-right { right: 0; left: auto; } .dropdown-menu-left { right: auto; left: 0; } .dropdown-header { display: block; padding: 3px 20px; font-size: 12px; line-height: 1.42857143; color: #777777; white-space: nowrap; } .dropdown-backdrop { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 990; } .pull-right > .dropdown-menu { right: 0; left: auto; } .dropup .caret, .navbar-fixed-bottom .dropdown .caret { content: ""; border-top: 0; border-bottom: 4px dashed; border-bottom: 4px solid \9; } .dropup .dropdown-menu, .navbar-fixed-bottom .dropdown .dropdown-menu { top: auto; bottom: 100%; margin-bottom: 2px; } @media (min-width: 768px) { .navbar-right .dropdown-menu { right: 0; left: auto; } .navbar-right .dropdown-menu-left { right: auto; left: 0; } } .btn-group, .btn-group-vertical { position: relative; display: inline-block; vertical-align: middle; } .btn-group > .btn, .btn-group-vertical > .btn { position: relative; float: left; } .btn-group > .btn:hover, .btn-group-vertical > .btn:hover, .btn-group > .btn:focus, .btn-group-vertical > .btn:focus, .btn-group > .btn:active, .btn-group-vertical > .btn:active, .btn-group > .btn.active, .btn-group-vertical > .btn.active { z-index: 2; } .btn-group .btn + .btn, .btn-group .btn + .btn-group, .btn-group .btn-group + .btn, .btn-group .btn-group + .btn-group { margin-left: -1px; } .btn-toolbar { margin-left: -5px; } .btn-toolbar .btn, .btn-toolbar .btn-group, .btn-toolbar .input-group { float: left; } .btn-toolbar > .btn, .btn-toolbar > .btn-group, .btn-toolbar > .input-group { margin-left: 5px; } .btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { border-radius: 0; } .btn-group > .btn:first-child { margin-left: 0; } .btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { border-top-right-radius: 0; border-bottom-right-radius: 0; } .btn-group > .btn:last-child:not(:first-child), .btn-group > .dropdown-toggle:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; } .btn-group > .btn-group { float: left; } .btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { border-radius: 0; } .btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, .btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { border-top-right-radius: 0; border-bottom-right-radius: 0; } .btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { border-top-left-radius: 0; border-bottom-left-radius: 0; } .btn-group .dropdown-toggle:active, .btn-group.open .dropdown-toggle { outline: 0; } .btn-group > .btn + .dropdown-toggle { padding-right: 8px; padding-left: 8px; } .btn-group > .btn-lg + .dropdown-toggle { padding-right: 12px; padding-left: 12px; } .btn-group.open .dropdown-toggle { -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); } .btn-group.open .dropdown-toggle.btn-link { -webkit-box-shadow: none; box-shadow: none; } .btn .caret { margin-left: 0; } .btn-lg .caret { border-width: 5px 5px 0; border-bottom-width: 0; } .dropup .btn-lg .caret { border-width: 0 5px 5px; } .btn-group-vertical > .btn, .btn-group-vertical > .btn-group, .btn-group-vertical > .btn-group > .btn { display: block; float: none; width: 100%; max-width: 100%; } .btn-group-vertical > .btn-group > .btn { float: none; } .btn-group-vertical > .btn + .btn, .btn-group-vertical > .btn + .btn-group, .btn-group-vertical > .btn-group + .btn, .btn-group-vertical > .btn-group + .btn-group { margin-top: -1px; margin-left: 0; } .btn-group-vertical > .btn:not(:first-child):not(:last-child) { border-radius: 0; } .btn-group-vertical > .btn:first-child:not(:last-child) { border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .btn-group-vertical > .btn:last-child:not(:first-child) { border-top-left-radius: 0; border-top-right-radius: 0; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; } .btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { border-radius: 0; } .btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, .btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { border-top-left-radius: 0; border-top-right-radius: 0; } .btn-group-justified { display: table; width: 100%; table-layout: fixed; border-collapse: separate; } .btn-group-justified > .btn, .btn-group-justified > .btn-group { display: table-cell; float: none; width: 1%; } .btn-group-justified > .btn-group .btn { width: 100%; } .btn-group-justified > .btn-group .dropdown-menu { left: auto; } [data-toggle="buttons"] > .btn input[type="radio"], [data-toggle="buttons"] > .btn-group > .btn input[type="radio"], [data-toggle="buttons"] > .btn input[type="checkbox"], [data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { position: absolute; clip: rect(0, 0, 0, 0); pointer-events: none; } .input-group { position: relative; display: table; border-collapse: separate; } .input-group[class*="col-"] { float: none; padding-right: 0; padding-left: 0; } .input-group .form-control { position: relative; z-index: 2; float: left; width: 100%; margin-bottom: 0; } .input-group .form-control:focus { z-index: 3; } .input-group-lg > .form-control, .input-group-lg > .input-group-addon, .input-group-lg > .input-group-btn > .btn { height: 46px; padding: 10px 16px; font-size: 18px; line-height: 1.3333333; border-radius: 6px; } select.input-group-lg > .form-control, select.input-group-lg > .input-group-addon, select.input-group-lg > .input-group-btn > .btn { height: 46px; line-height: 46px; } textarea.input-group-lg > .form-control, textarea.input-group-lg > .input-group-addon, textarea.input-group-lg > .input-group-btn > .btn, select[multiple].input-group-lg > .form-control, select[multiple].input-group-lg > .input-group-addon, select[multiple].input-group-lg > .input-group-btn > .btn { height: auto; } .input-group-sm > .form-control, .input-group-sm > .input-group-addon, .input-group-sm > .input-group-btn > .btn { height: 30px; padding: 5px 10px; font-size: 12px; line-height: 1.5; border-radius: 3px; } select.input-group-sm > .form-control, select.input-group-sm > .input-group-addon, select.input-group-sm > .input-group-btn > .btn { height: 30px; line-height: 30px; } textarea.input-group-sm > .form-control, textarea.input-group-sm > .input-group-addon, textarea.input-group-sm > .input-group-btn > .btn, select[multiple].input-group-sm > .form-control, select[multiple].input-group-sm > .input-group-addon, select[multiple].input-group-sm > .input-group-btn > .btn { height: auto; } .input-group-addon, .input-group-btn, .input-group .form-control { display: table-cell; } .input-group-addon:not(:first-child):not(:last-child), .input-group-btn:not(:first-child):not(:last-child), .input-group .form-control:not(:first-child):not(:last-child) { border-radius: 0; } .input-group-addon, .input-group-btn { width: 1%; white-space: nowrap; vertical-align: middle; } .input-group-addon { padding: 6px 12px; font-size: 14px; font-weight: 400; line-height: 1; color: #555555; text-align: center; background-color: #eeeeee; border: 1px solid #ccc; border-radius: 4px; } .input-group-addon.input-sm { padding: 5px 10px; font-size: 12px; border-radius: 3px; } .input-group-addon.input-lg { padding: 10px 16px; font-size: 18px; border-radius: 6px; } .input-group-addon input[type="radio"], .input-group-addon input[type="checkbox"] { margin-top: 0; } .input-group .form-control:first-child, .input-group-addon:first-child, .input-group-btn:first-child > .btn, .input-group-btn:first-child > .btn-group > .btn, .input-group-btn:first-child > .dropdown-toggle, .input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), .input-group-btn:last-child > .btn-group:not(:last-child) > .btn { border-top-right-radius: 0; border-bottom-right-radius: 0; } .input-group-addon:first-child { border-right: 0; } .input-group .form-control:last-child, .input-group-addon:last-child, .input-group-btn:last-child > .btn, .input-group-btn:last-child > .btn-group > .btn, .input-group-btn:last-child > .dropdown-toggle, .input-group-btn:first-child > .btn:not(:first-child), .input-group-btn:first-child > .btn-group:not(:first-child) > .btn { border-top-left-radius: 0; border-bottom-left-radius: 0; } .input-group-addon:last-child { border-left: 0; } .input-group-btn { position: relative; font-size: 0; white-space: nowrap; } .input-group-btn > .btn { position: relative; } .input-group-btn > .btn + .btn { margin-left: -1px; } .input-group-btn > .btn:hover, .input-group-btn > .btn:focus, .input-group-btn > .btn:active { z-index: 2; } .input-group-btn:first-child > .btn, .input-group-btn:first-child > .btn-group { margin-right: -1px; } .input-group-btn:last-child > .btn, .input-group-btn:last-child > .btn-group { z-index: 2; margin-left: -1px; } .nav { padding-left: 0; margin-bottom: 0; list-style: none; } .nav > li { position: relative; display: block; } .nav > li > a { position: relative; display: block; padding: 10px 15px; } .nav > li > a:hover, .nav > li > a:focus { text-decoration: none; background-color: #eeeeee; } .nav > li.disabled > a { color: #777777; } .nav > li.disabled > a:hover, .nav > li.disabled > a:focus { color: #777777; text-decoration: none; cursor: not-allowed; background-color: transparent; } .nav .open > a, .nav .open > a:hover, .nav .open > a:focus { background-color: #eeeeee; border-color: #337ab7; } .nav .nav-divider { height: 1px; margin: 9px 0; overflow: hidden; background-color: #e5e5e5; } .nav > li > a > img { max-width: none; } .nav-tabs { border-bottom: 1px solid #ddd; } .nav-tabs > li { float: left; margin-bottom: -1px; } .nav-tabs > li > a { margin-right: 2px; line-height: 1.42857143; border: 1px solid transparent; border-radius: 4px 4px 0 0; } .nav-tabs > li > a:hover { border-color: #eeeeee #eeeeee #ddd; } .nav-tabs > li.active > a, .nav-tabs > li.active > a:hover, .nav-tabs > li.active > a:focus { color: #555555; cursor: default; background-color: #fff; border: 1px solid #ddd; border-bottom-color: transparent; } .nav-tabs.nav-justified { width: 100%; border-bottom: 0; } .nav-tabs.nav-justified > li { float: none; } .nav-tabs.nav-justified > li > a { margin-bottom: 5px; text-align: center; } .nav-tabs.nav-justified > .dropdown .dropdown-menu { top: auto; left: auto; } @media (min-width: 768px) { .nav-tabs.nav-justified > li { display: table-cell; width: 1%; } .nav-tabs.nav-justified > li > a { margin-bottom: 0; } } .nav-tabs.nav-justified > li > a { margin-right: 0; border-radius: 4px; } .nav-tabs.nav-justified > .active > a, .nav-tabs.nav-justified > .active > a:hover, .nav-tabs.nav-justified > .active > a:focus { border: 1px solid #ddd; } @media (min-width: 768px) { .nav-tabs.nav-justified > li > a { border-bottom: 1px solid #ddd; border-radius: 4px 4px 0 0; } .nav-tabs.nav-justified > .active > a, .nav-tabs.nav-justified > .active > a:hover, .nav-tabs.nav-justified > .active > a:focus { border-bottom-color: #fff; } } .nav-pills > li { float: left; } .nav-pills > li > a { border-radius: 4px; } .nav-pills > li + li { margin-left: 2px; } .nav-pills > li.active > a, .nav-pills > li.active > a:hover, .nav-pills > li.active > a:focus { color: #fff; background-color: #337ab7; } .nav-stacked > li { float: none; } .nav-stacked > li + li { margin-top: 2px; margin-left: 0; } .nav-justified { width: 100%; } .nav-justified > li { float: none; } .nav-justified > li > a { margin-bottom: 5px; text-align: center; } .nav-justified > .dropdown .dropdown-menu { top: auto; left: auto; } @media (min-width: 768px) { .nav-justified > li { display: table-cell; width: 1%; } .nav-justified > li > a { margin-bottom: 0; } } .nav-tabs-justified { border-bottom: 0; } .nav-tabs-justified > li > a { margin-right: 0; border-radius: 4px; } .nav-tabs-justified > .active > a, .nav-tabs-justified > .active > a:hover, .nav-tabs-justified > .active > a:focus { border: 1px solid #ddd; } @media (min-width: 768px) { .nav-tabs-justified > li > a { border-bottom: 1px solid #ddd; border-radius: 4px 4px 0 0; } .nav-tabs-justified > .active > a, .nav-tabs-justified > .active > a:hover, .nav-tabs-justified > .active > a:focus { border-bottom-color: #fff; } } .tab-content > .tab-pane { display: none; } .tab-content > .active { display: block; } .nav-tabs .dropdown-menu { margin-top: -1px; border-top-left-radius: 0; border-top-right-radius: 0; } .navbar { position: relative; min-height: 50px; margin-bottom: 20px; border: 1px solid transparent; } @media (min-width: 768px) { .navbar { border-radius: 4px; } } @media (min-width: 768px) { .navbar-header { float: left; } } .navbar-collapse { padding-right: 15px; padding-left: 15px; overflow-x: visible; border-top: 1px solid transparent; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); -webkit-overflow-scrolling: touch; } .navbar-collapse.in { overflow-y: auto; } @media (min-width: 768px) { .navbar-collapse { width: auto; border-top: 0; -webkit-box-shadow: none; box-shadow: none; } .navbar-collapse.collapse { display: block !important; height: auto !important; padding-bottom: 0; overflow: visible !important; } .navbar-collapse.in { overflow-y: visible; } .navbar-fixed-top .navbar-collapse, .navbar-static-top .navbar-collapse, .navbar-fixed-bottom .navbar-collapse { padding-right: 0; padding-left: 0; } } .navbar-fixed-top, .navbar-fixed-bottom { position: fixed; right: 0; left: 0; z-index: 1030; } .navbar-fixed-top .navbar-collapse, .navbar-fixed-bottom .navbar-collapse { max-height: 340px; } @media (max-device-width: 480px) and (orientation: landscape) { .navbar-fixed-top .navbar-collapse, .navbar-fixed-bottom .navbar-collapse { max-height: 200px; } } @media (min-width: 768px) { .navbar-fixed-top, .navbar-fixed-bottom { border-radius: 0; } } .navbar-fixed-top { top: 0; border-width: 0 0 1px; } .navbar-fixed-bottom { bottom: 0; margin-bottom: 0; border-width: 1px 0 0; } .container > .navbar-header, .container-fluid > .navbar-header, .container > .navbar-collapse, .container-fluid > .navbar-collapse { margin-right: -15px; margin-left: -15px; } @media (min-width: 768px) { .container > .navbar-header, .container-fluid > .navbar-header, .container > .navbar-collapse, .container-fluid > .navbar-collapse { margin-right: 0; margin-left: 0; } } .navbar-static-top { z-index: 1000; border-width: 0 0 1px; } @media (min-width: 768px) { .navbar-static-top { border-radius: 0; } } .navbar-brand { float: left; height: 50px; padding: 15px 15px; font-size: 18px; line-height: 20px; } .navbar-brand:hover, .navbar-brand:focus { text-decoration: none; } .navbar-brand > img { display: block; } @media (min-width: 768px) { .navbar > .container .navbar-brand, .navbar > .container-fluid .navbar-brand { margin-left: -15px; } } .navbar-toggle { position: relative; float: right; padding: 9px 10px; margin-right: 15px; margin-top: 8px; margin-bottom: 8px; background-color: transparent; background-image: none; border: 1px solid transparent; border-radius: 4px; } .navbar-toggle:focus { outline: 0; } .navbar-toggle .icon-bar { display: block; width: 22px; height: 2px; border-radius: 1px; } .navbar-toggle .icon-bar + .icon-bar { margin-top: 4px; } @media (min-width: 768px) { .navbar-toggle { display: none; } } .navbar-nav { margin: 7.5px -15px; } .navbar-nav > li > a { padding-top: 10px; padding-bottom: 10px; line-height: 20px; } @media (max-width: 767px) { .navbar-nav .open .dropdown-menu { position: static; float: none; width: auto; margin-top: 0; background-color: transparent; border: 0; -webkit-box-shadow: none; box-shadow: none; } .navbar-nav .open .dropdown-menu > li > a, .navbar-nav .open .dropdown-menu .dropdown-header { padding: 5px 15px 5px 25px; } .navbar-nav .open .dropdown-menu > li > a { line-height: 20px; } .navbar-nav .open .dropdown-menu > li > a:hover, .navbar-nav .open .dropdown-menu > li > a:focus { background-image: none; } } @media (min-width: 768px) { .navbar-nav { float: left; margin: 0; } .navbar-nav > li { float: left; } .navbar-nav > li > a { padding-top: 15px; padding-bottom: 15px; } } .navbar-form { padding: 10px 15px; margin-right: -15px; margin-left: -15px; border-top: 1px solid transparent; border-bottom: 1px solid transparent; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); margin-top: 8px; margin-bottom: 8px; } @media (min-width: 768px) { .navbar-form .form-group { display: inline-block; margin-bottom: 0; vertical-align: middle; } .navbar-form .form-control { display: inline-block; width: auto; vertical-align: middle; } .navbar-form .form-control-static { display: inline-block; } .navbar-form .input-group { display: inline-table; vertical-align: middle; } .navbar-form .input-group .input-group-addon, .navbar-form .input-group .input-group-btn, .navbar-form .input-group .form-control { width: auto; } .navbar-form .input-group > .form-control { width: 100%; } .navbar-form .control-label { margin-bottom: 0; vertical-align: middle; } .navbar-form .radio, .navbar-form .checkbox { display: inline-block; margin-top: 0; margin-bottom: 0; vertical-align: middle; } .navbar-form .radio label, .navbar-form .checkbox label { padding-left: 0; } .navbar-form .radio input[type="radio"], .navbar-form .checkbox input[type="checkbox"] { position: relative; margin-left: 0; } .navbar-form .has-feedback .form-control-feedback { top: 0; } } @media (max-width: 767px) { .navbar-form .form-group { margin-bottom: 5px; } .navbar-form .form-group:last-child { margin-bottom: 0; } } @media (min-width: 768px) { .navbar-form { width: auto; padding-top: 0; padding-bottom: 0; margin-right: 0; margin-left: 0; border: 0; -webkit-box-shadow: none; box-shadow: none; } } .navbar-nav > li > .dropdown-menu { margin-top: 0; border-top-left-radius: 0; border-top-right-radius: 0; } .navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { margin-bottom: 0; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .navbar-btn { margin-top: 8px; margin-bottom: 8px; } .navbar-btn.btn-sm { margin-top: 10px; margin-bottom: 10px; } .navbar-btn.btn-xs { margin-top: 14px; margin-bottom: 14px; } .navbar-text { margin-top: 15px; margin-bottom: 15px; } @media (min-width: 768px) { .navbar-text { float: left; margin-right: 15px; margin-left: 15px; } } @media (min-width: 768px) { .navbar-left { float: left !important; } .navbar-right { float: right !important; margin-right: -15px; } .navbar-right ~ .navbar-right { margin-right: 0; } } .navbar-default { background-color: #f8f8f8; border-color: #e7e7e7; } .navbar-default .navbar-brand { color: #777; } .navbar-default .navbar-brand:hover, .navbar-default .navbar-brand:focus { color: #5e5e5e; background-color: transparent; } .navbar-default .navbar-text { color: #777; } .navbar-default .navbar-nav > li > a { color: #777; } .navbar-default .navbar-nav > li > a:hover, .navbar-default .navbar-nav > li > a:focus { color: #333; background-color: transparent; } .navbar-default .navbar-nav > .active > a, .navbar-default .navbar-nav > .active > a:hover, .navbar-default .navbar-nav > .active > a:focus { color: #555; background-color: #e7e7e7; } .navbar-default .navbar-nav > .disabled > a, .navbar-default .navbar-nav > .disabled > a:hover, .navbar-default .navbar-nav > .disabled > a:focus { color: #ccc; background-color: transparent; } .navbar-default .navbar-nav > .open > a, .navbar-default .navbar-nav > .open > a:hover, .navbar-default .navbar-nav > .open > a:focus { color: #555; background-color: #e7e7e7; } @media (max-width: 767px) { .navbar-default .navbar-nav .open .dropdown-menu > li > a { color: #777; } .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { color: #333; background-color: transparent; } .navbar-default .navbar-nav .open .dropdown-menu > .active > a, .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { color: #555; background-color: #e7e7e7; } .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { color: #ccc; background-color: transparent; } } .navbar-default .navbar-toggle { border-color: #ddd; } .navbar-default .navbar-toggle:hover, .navbar-default .navbar-toggle:focus { background-color: #ddd; } .navbar-default .navbar-toggle .icon-bar { background-color: #888; } .navbar-default .navbar-collapse, .navbar-default .navbar-form { border-color: #e7e7e7; } .navbar-default .navbar-link { color: #777; } .navbar-default .navbar-link:hover { color: #333; } .navbar-default .btn-link { color: #777; } .navbar-default .btn-link:hover, .navbar-default .btn-link:focus { color: #333; } .navbar-default .btn-link[disabled]:hover, fieldset[disabled] .navbar-default .btn-link:hover, .navbar-default .btn-link[disabled]:focus, fieldset[disabled] .navbar-default .btn-link:focus { color: #ccc; } .navbar-inverse { background-color: #222; border-color: #080808; } .navbar-inverse .navbar-brand { color: #9d9d9d; } .navbar-inverse .navbar-brand:hover, .navbar-inverse .navbar-brand:focus { color: #fff; background-color: transparent; } .navbar-inverse .navbar-text { color: #9d9d9d; } .navbar-inverse .navbar-nav > li > a { color: #9d9d9d; } .navbar-inverse .navbar-nav > li > a:hover, .navbar-inverse .navbar-nav > li > a:focus { color: #fff; background-color: transparent; } .navbar-inverse .navbar-nav > .active > a, .navbar-inverse .navbar-nav > .active > a:hover, .navbar-inverse .navbar-nav > .active > a:focus { color: #fff; background-color: #080808; } .navbar-inverse .navbar-nav > .disabled > a, .navbar-inverse .navbar-nav > .disabled > a:hover, .navbar-inverse .navbar-nav > .disabled > a:focus { color: #444; background-color: transparent; } .navbar-inverse .navbar-nav > .open > a, .navbar-inverse .navbar-nav > .open > a:hover, .navbar-inverse .navbar-nav > .open > a:focus { color: #fff; background-color: #080808; } @media (max-width: 767px) { .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { border-color: #080808; } .navbar-inverse .navbar-nav .open .dropdown-menu .divider { background-color: #080808; } .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { color: #9d9d9d; } .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { color: #fff; background-color: transparent; } .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { color: #fff; background-color: #080808; } .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { color: #444; background-color: transparent; } } .navbar-inverse .navbar-toggle { border-color: #333; } .navbar-inverse .navbar-toggle:hover, .navbar-inverse .navbar-toggle:focus { background-color: #333; } .navbar-inverse .navbar-toggle .icon-bar { background-color: #fff; } .navbar-inverse .navbar-collapse, .navbar-inverse .navbar-form { border-color: #101010; } .navbar-inverse .navbar-link { color: #9d9d9d; } .navbar-inverse .navbar-link:hover { color: #fff; } .navbar-inverse .btn-link { color: #9d9d9d; } .navbar-inverse .btn-link:hover, .navbar-inverse .btn-link:focus { color: #fff; } .navbar-inverse .btn-link[disabled]:hover, fieldset[disabled] .navbar-inverse .btn-link:hover, .navbar-inverse .btn-link[disabled]:focus, fieldset[disabled] .navbar-inverse .btn-link:focus { color: #444; } .breadcrumb { padding: 8px 15px; margin-bottom: 20px; list-style: none; background-color: #f5f5f5; border-radius: 4px; } .breadcrumb > li { display: inline-block; } .breadcrumb > li + li:before { padding: 0 5px; color: #ccc; content: "/\00a0"; } .breadcrumb > .active { color: #777777; } .pagination { display: inline-block; padding-left: 0; margin: 20px 0; border-radius: 4px; } .pagination > li { display: inline; } .pagination > li > a, .pagination > li > span { position: relative; float: left; padding: 6px 12px; margin-left: -1px; line-height: 1.42857143; color: #337ab7; text-decoration: none; background-color: #fff; border: 1px solid #ddd; } .pagination > li > a:hover, .pagination > li > span:hover, .pagination > li > a:focus, .pagination > li > span:focus { z-index: 2; color: #23527c; background-color: #eeeeee; border-color: #ddd; } .pagination > li:first-child > a, .pagination > li:first-child > span { margin-left: 0; border-top-left-radius: 4px; border-bottom-left-radius: 4px; } .pagination > li:last-child > a, .pagination > li:last-child > span { border-top-right-radius: 4px; border-bottom-right-radius: 4px; } .pagination > .active > a, .pagination > .active > span, .pagination > .active > a:hover, .pagination > .active > span:hover, .pagination > .active > a:focus, .pagination > .active > span:focus { z-index: 3; color: #fff; cursor: default; background-color: #337ab7; border-color: #337ab7; } .pagination > .disabled > span, .pagination > .disabled > span:hover, .pagination > .disabled > span:focus, .pagination > .disabled > a, .pagination > .disabled > a:hover, .pagination > .disabled > a:focus { color: #777777; cursor: not-allowed; background-color: #fff; border-color: #ddd; } .pagination-lg > li > a, .pagination-lg > li > span { padding: 10px 16px; font-size: 18px; line-height: 1.3333333; } .pagination-lg > li:first-child > a, .pagination-lg > li:first-child > span { border-top-left-radius: 6px; border-bottom-left-radius: 6px; } .pagination-lg > li:last-child > a, .pagination-lg > li:last-child > span { border-top-right-radius: 6px; border-bottom-right-radius: 6px; } .pagination-sm > li > a, .pagination-sm > li > span { padding: 5px 10px; font-size: 12px; line-height: 1.5; } .pagination-sm > li:first-child > a, .pagination-sm > li:first-child > span { border-top-left-radius: 3px; border-bottom-left-radius: 3px; } .pagination-sm > li:last-child > a, .pagination-sm > li:last-child > span { border-top-right-radius: 3px; border-bottom-right-radius: 3px; } .pager { padding-left: 0; margin: 20px 0; text-align: center; list-style: none; } .pager li { display: inline; } .pager li > a, .pager li > span { display: inline-block; padding: 5px 14px; background-color: #fff; border: 1px solid #ddd; border-radius: 15px; } .pager li > a:hover, .pager li > a:focus { text-decoration: none; background-color: #eeeeee; } .pager .next > a, .pager .next > span { float: right; } .pager .previous > a, .pager .previous > span { float: left; } .pager .disabled > a, .pager .disabled > a:hover, .pager .disabled > a:focus, .pager .disabled > span { color: #777777; cursor: not-allowed; background-color: #fff; } .label { display: inline; padding: 0.2em 0.6em 0.3em; font-size: 75%; font-weight: 700; line-height: 1; color: #fff; text-align: center; white-space: nowrap; vertical-align: baseline; border-radius: 0.25em; } a.label:hover, a.label:focus { color: #fff; text-decoration: none; cursor: pointer; } .label:empty { display: none; } .btn .label { position: relative; top: -1px; } .label-default { background-color: #777777; } .label-default[href]:hover, .label-default[href]:focus { background-color: #5e5e5e; } .label-primary { background-color: #337ab7; } .label-primary[href]:hover, .label-primary[href]:focus { background-color: #286090; } .label-success { background-color: #5cb85c; } .label-success[href]:hover, .label-success[href]:focus { background-color: #449d44; } .label-info { background-color: #5bc0de; } .label-info[href]:hover, .label-info[href]:focus { background-color: #31b0d5; } .label-warning { background-color: #f0ad4e; } .label-warning[href]:hover, .label-warning[href]:focus { background-color: #ec971f; } .label-danger { background-color: #d9534f; } .label-danger[href]:hover, .label-danger[href]:focus { background-color: #c9302c; } .badge { display: inline-block; min-width: 10px; padding: 3px 7px; font-size: 12px; font-weight: bold; line-height: 1; color: #fff; text-align: center; white-space: nowrap; vertical-align: middle; background-color: #777777; border-radius: 10px; } .badge:empty { display: none; } .btn .badge { position: relative; top: -1px; } .btn-xs .badge, .btn-group-xs > .btn .badge { top: 0; padding: 1px 5px; } a.badge:hover, a.badge:focus { color: #fff; text-decoration: none; cursor: pointer; } .list-group-item.active > .badge, .nav-pills > .active > a > .badge { color: #337ab7; background-color: #fff; } .list-group-item > .badge { float: right; } .list-group-item > .badge + .badge { margin-right: 5px; } .nav-pills > li > a > .badge { margin-left: 3px; } .jumbotron { padding-top: 30px; padding-bottom: 30px; margin-bottom: 30px; color: inherit; background-color: #eeeeee; } .jumbotron h1, .jumbotron .h1 { color: inherit; } .jumbotron p { margin-bottom: 15px; font-size: 21px; font-weight: 200; } .jumbotron > hr { border-top-color: #d5d5d5; } .container .jumbotron, .container-fluid .jumbotron { padding-right: 15px; padding-left: 15px; border-radius: 6px; } .jumbotron .container { max-width: 100%; } @media screen and (min-width: 768px) { .jumbotron { padding-top: 48px; padding-bottom: 48px; } .container .jumbotron, .container-fluid .jumbotron { padding-right: 60px; padding-left: 60px; } .jumbotron h1, .jumbotron .h1 { font-size: 63px; } } .thumbnail { display: block; padding: 4px; margin-bottom: 20px; line-height: 1.42857143; background-color: #fff; border: 1px solid #ddd; border-radius: 4px; -webkit-transition: border 0.2s ease-in-out; -o-transition: border 0.2s ease-in-out; transition: border 0.2s ease-in-out; } .thumbnail > img, .thumbnail a > img { margin-right: auto; margin-left: auto; } a.thumbnail:hover, a.thumbnail:focus, a.thumbnail.active { border-color: #337ab7; } .thumbnail .caption { padding: 9px; color: #333333; } .alert { padding: 15px; margin-bottom: 20px; border: 1px solid transparent; border-radius: 4px; } .alert h4 { margin-top: 0; color: inherit; } .alert .alert-link { font-weight: bold; } .alert > p, .alert > ul { margin-bottom: 0; } .alert > p + p { margin-top: 5px; } .alert-dismissable, .alert-dismissible { padding-right: 35px; } .alert-dismissable .close, .alert-dismissible .close { position: relative; top: -2px; right: -21px; color: inherit; } .alert-success { color: #3c763d; background-color: #dff0d8; border-color: #d6e9c6; } .alert-success hr { border-top-color: #c9e2b3; } .alert-success .alert-link { color: #2b542c; } .alert-info { color: #31708f; background-color: #d9edf7; border-color: #bce8f1; } .alert-info hr { border-top-color: #a6e1ec; } .alert-info .alert-link { color: #245269; } .alert-warning { color: #8a6d3b; background-color: #fcf8e3; border-color: #faebcc; } .alert-warning hr { border-top-color: #f7e1b5; } .alert-warning .alert-link { color: #66512c; } .alert-danger { color: #a94442; background-color: #f2dede; border-color: #ebccd1; } .alert-danger hr { border-top-color: #e4b9c0; } .alert-danger .alert-link { color: #843534; } @-webkit-keyframes progress-bar-stripes { from { background-position: 40px 0; } to { background-position: 0 0; } } @-o-keyframes progress-bar-stripes { from { background-position: 40px 0; } to { background-position: 0 0; } } @keyframes progress-bar-stripes { from { background-position: 40px 0; } to { background-position: 0 0; } } .progress { height: 20px; margin-bottom: 20px; overflow: hidden; background-color: #f5f5f5; border-radius: 4px; -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); } .progress-bar { float: left; width: 0%; height: 100%; font-size: 12px; line-height: 20px; color: #fff; text-align: center; background-color: #337ab7; -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); -webkit-transition: width 0.6s ease; -o-transition: width 0.6s ease; transition: width 0.6s ease; } .progress-striped .progress-bar, .progress-bar-striped { background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -webkit-background-size: 40px 40px; background-size: 40px 40px; } .progress.active .progress-bar, .progress-bar.active { -webkit-animation: progress-bar-stripes 2s linear infinite; -o-animation: progress-bar-stripes 2s linear infinite; animation: progress-bar-stripes 2s linear infinite; } .progress-bar-success { background-color: #5cb85c; } .progress-striped .progress-bar-success { background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .progress-bar-info { background-color: #5bc0de; } .progress-striped .progress-bar-info { background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .progress-bar-warning { background-color: #f0ad4e; } .progress-striped .progress-bar-warning { background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .progress-bar-danger { background-color: #d9534f; } .progress-striped .progress-bar-danger { background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .media { margin-top: 15px; } .media:first-child { margin-top: 0; } .media, .media-body { overflow: hidden; zoom: 1; } .media-body { width: 10000px; } .media-object { display: block; } .media-object.img-thumbnail { max-width: none; } .media-right, .media > .pull-right { padding-left: 10px; } .media-left, .media > .pull-left { padding-right: 10px; } .media-left, .media-right, .media-body { display: table-cell; vertical-align: top; } .media-middle { vertical-align: middle; } .media-bottom { vertical-align: bottom; } .media-heading { margin-top: 0; margin-bottom: 5px; } .media-list { padding-left: 0; list-style: none; } .list-group { padding-left: 0; margin-bottom: 20px; } .list-group-item { position: relative; display: block; padding: 10px 15px; margin-bottom: -1px; background-color: #fff; border: 1px solid #ddd; } .list-group-item:first-child { border-top-left-radius: 4px; border-top-right-radius: 4px; } .list-group-item:last-child { margin-bottom: 0; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; } .list-group-item.disabled, .list-group-item.disabled:hover, .list-group-item.disabled:focus { color: #777777; cursor: not-allowed; background-color: #eeeeee; } .list-group-item.disabled .list-group-item-heading, .list-group-item.disabled:hover .list-group-item-heading, .list-group-item.disabled:focus .list-group-item-heading { color: inherit; } .list-group-item.disabled .list-group-item-text, .list-group-item.disabled:hover .list-group-item-text, .list-group-item.disabled:focus .list-group-item-text { color: #777777; } .list-group-item.active, .list-group-item.active:hover, .list-group-item.active:focus { z-index: 2; color: #fff; background-color: #337ab7; border-color: #337ab7; } .list-group-item.active .list-group-item-heading, .list-group-item.active:hover .list-group-item-heading, .list-group-item.active:focus .list-group-item-heading, .list-group-item.active .list-group-item-heading > small, .list-group-item.active:hover .list-group-item-heading > small, .list-group-item.active:focus .list-group-item-heading > small, .list-group-item.active .list-group-item-heading > .small, .list-group-item.active:hover .list-group-item-heading > .small, .list-group-item.active:focus .list-group-item-heading > .small { color: inherit; } .list-group-item.active .list-group-item-text, .list-group-item.active:hover .list-group-item-text, .list-group-item.active:focus .list-group-item-text { color: #c7ddef; } a.list-group-item, button.list-group-item { color: #555; } a.list-group-item .list-group-item-heading, button.list-group-item .list-group-item-heading { color: #333; } a.list-group-item:hover, button.list-group-item:hover, a.list-group-item:focus, button.list-group-item:focus { color: #555; text-decoration: none; background-color: #f5f5f5; } button.list-group-item { width: 100%; text-align: left; } .list-group-item-success { color: #3c763d; background-color: #dff0d8; } a.list-group-item-success, button.list-group-item-success { color: #3c763d; } a.list-group-item-success .list-group-item-heading, button.list-group-item-success .list-group-item-heading { color: inherit; } a.list-group-item-success:hover, button.list-group-item-success:hover, a.list-group-item-success:focus, button.list-group-item-success:focus { color: #3c763d; background-color: #d0e9c6; } a.list-group-item-success.active, button.list-group-item-success.active, a.list-group-item-success.active:hover, button.list-group-item-success.active:hover, a.list-group-item-success.active:focus, button.list-group-item-success.active:focus { color: #fff; background-color: #3c763d; border-color: #3c763d; } .list-group-item-info { color: #31708f; background-color: #d9edf7; } a.list-group-item-info, button.list-group-item-info { color: #31708f; } a.list-group-item-info .list-group-item-heading, button.list-group-item-info .list-group-item-heading { color: inherit; } a.list-group-item-info:hover, button.list-group-item-info:hover, a.list-group-item-info:focus, button.list-group-item-info:focus { color: #31708f; background-color: #c4e3f3; } a.list-group-item-info.active, button.list-group-item-info.active, a.list-group-item-info.active:hover, button.list-group-item-info.active:hover, a.list-group-item-info.active:focus, button.list-group-item-info.active:focus { color: #fff; background-color: #31708f; border-color: #31708f; } .list-group-item-warning { color: #8a6d3b; background-color: #fcf8e3; } a.list-group-item-warning, button.list-group-item-warning { color: #8a6d3b; } a.list-group-item-warning .list-group-item-heading, button.list-group-item-warning .list-group-item-heading { color: inherit; } a.list-group-item-warning:hover, button.list-group-item-warning:hover, a.list-group-item-warning:focus, button.list-group-item-warning:focus { color: #8a6d3b; background-color: #faf2cc; } a.list-group-item-warning.active, button.list-group-item-warning.active, a.list-group-item-warning.active:hover, button.list-group-item-warning.active:hover, a.list-group-item-warning.active:focus, button.list-group-item-warning.active:focus { color: #fff; background-color: #8a6d3b; border-color: #8a6d3b; } .list-group-item-danger { color: #a94442; background-color: #f2dede; } a.list-group-item-danger, button.list-group-item-danger { color: #a94442; } a.list-group-item-danger .list-group-item-heading, button.list-group-item-danger .list-group-item-heading { color: inherit; } a.list-group-item-danger:hover, button.list-group-item-danger:hover, a.list-group-item-danger:focus, button.list-group-item-danger:focus { color: #a94442; background-color: #ebcccc; } a.list-group-item-danger.active, button.list-group-item-danger.active, a.list-group-item-danger.active:hover, button.list-group-item-danger.active:hover, a.list-group-item-danger.active:focus, button.list-group-item-danger.active:focus { color: #fff; background-color: #a94442; border-color: #a94442; } .list-group-item-heading { margin-top: 0; margin-bottom: 5px; } .list-group-item-text { margin-bottom: 0; line-height: 1.3; } .panel { margin-bottom: 20px; background-color: #fff; border: 1px solid transparent; border-radius: 4px; -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); } .panel-body { padding: 15px; } .panel-heading { padding: 10px 15px; border-bottom: 1px solid transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; } .panel-heading > .dropdown .dropdown-toggle { color: inherit; } .panel-title { margin-top: 0; margin-bottom: 0; font-size: 16px; color: inherit; } .panel-title > a, .panel-title > small, .panel-title > .small, .panel-title > small > a, .panel-title > .small > a { color: inherit; } .panel-footer { padding: 10px 15px; background-color: #f5f5f5; border-top: 1px solid #ddd; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; } .panel > .list-group, .panel > .panel-collapse > .list-group { margin-bottom: 0; } .panel > .list-group .list-group-item, .panel > .panel-collapse > .list-group .list-group-item { border-width: 1px 0; border-radius: 0; } .panel > .list-group:first-child .list-group-item:first-child, .panel > .panel-collapse > .list-group:first-child .list-group-item:first-child { border-top: 0; border-top-left-radius: 3px; border-top-right-radius: 3px; } .panel > .list-group:last-child .list-group-item:last-child, .panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { border-bottom: 0; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; } .panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child { border-top-left-radius: 0; border-top-right-radius: 0; } .panel-heading + .list-group .list-group-item:first-child { border-top-width: 0; } .list-group + .panel-footer { border-top-width: 0; } .panel > .table, .panel > .table-responsive > .table, .panel > .panel-collapse > .table { margin-bottom: 0; } .panel > .table caption, .panel > .table-responsive > .table caption, .panel > .panel-collapse > .table caption { padding-right: 15px; padding-left: 15px; } .panel > .table:first-child, .panel > .table-responsive:first-child > .table:first-child { border-top-left-radius: 3px; border-top-right-radius: 3px; } .panel > .table:first-child > thead:first-child > tr:first-child, .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, .panel > .table:first-child > tbody:first-child > tr:first-child, .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { border-top-left-radius: 3px; border-top-right-radius: 3px; } .panel > .table:first-child > thead:first-child > tr:first-child td:first-child, .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, .panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, .panel > .table:first-child > thead:first-child > tr:first-child th:first-child, .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, .panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { border-top-left-radius: 3px; } .panel > .table:first-child > thead:first-child > tr:first-child td:last-child, .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, .panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, .panel > .table:first-child > thead:first-child > tr:first-child th:last-child, .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, .panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { border-top-right-radius: 3px; } .panel > .table:last-child, .panel > .table-responsive:last-child > .table:last-child { border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; } .panel > .table:last-child > tbody:last-child > tr:last-child, .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, .panel > .table:last-child > tfoot:last-child > tr:last-child, .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; } .panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, .panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, .panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, .panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { border-bottom-left-radius: 3px; } .panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, .panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, .panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, .panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { border-bottom-right-radius: 3px; } .panel > .panel-body + .table, .panel > .panel-body + .table-responsive, .panel > .table + .panel-body, .panel > .table-responsive + .panel-body { border-top: 1px solid #ddd; } .panel > .table > tbody:first-child > tr:first-child th, .panel > .table > tbody:first-child > tr:first-child td { border-top: 0; } .panel > .table-bordered, .panel > .table-responsive > .table-bordered { border: 0; } .panel > .table-bordered > thead > tr > th:first-child, .panel > .table-responsive > .table-bordered > thead > tr > th:first-child, .panel > .table-bordered > tbody > tr > th:first-child, .panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, .panel > .table-bordered > tfoot > tr > th:first-child, .panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, .panel > .table-bordered > thead > tr > td:first-child, .panel > .table-responsive > .table-bordered > thead > tr > td:first-child, .panel > .table-bordered > tbody > tr > td:first-child, .panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, .panel > .table-bordered > tfoot > tr > td:first-child, .panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { border-left: 0; } .panel > .table-bordered > thead > tr > th:last-child, .panel > .table-responsive > .table-bordered > thead > tr > th:last-child, .panel > .table-bordered > tbody > tr > th:last-child, .panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, .panel > .table-bordered > tfoot > tr > th:last-child, .panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, .panel > .table-bordered > thead > tr > td:last-child, .panel > .table-responsive > .table-bordered > thead > tr > td:last-child, .panel > .table-bordered > tbody > tr > td:last-child, .panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, .panel > .table-bordered > tfoot > tr > td:last-child, .panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { border-right: 0; } .panel > .table-bordered > thead > tr:first-child > td, .panel > .table-responsive > .table-bordered > thead > tr:first-child > td, .panel > .table-bordered > tbody > tr:first-child > td, .panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, .panel > .table-bordered > thead > tr:first-child > th, .panel > .table-responsive > .table-bordered > thead > tr:first-child > th, .panel > .table-bordered > tbody > tr:first-child > th, .panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { border-bottom: 0; } .panel > .table-bordered > tbody > tr:last-child > td, .panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, .panel > .table-bordered > tfoot > tr:last-child > td, .panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, .panel > .table-bordered > tbody > tr:last-child > th, .panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, .panel > .table-bordered > tfoot > tr:last-child > th, .panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { border-bottom: 0; } .panel > .table-responsive { margin-bottom: 0; border: 0; } .panel-group { margin-bottom: 20px; } .panel-group .panel { margin-bottom: 0; border-radius: 4px; } .panel-group .panel + .panel { margin-top: 5px; } .panel-group .panel-heading { border-bottom: 0; } .panel-group .panel-heading + .panel-collapse > .panel-body, .panel-group .panel-heading + .panel-collapse > .list-group { border-top: 1px solid #ddd; } .panel-group .panel-footer { border-top: 0; } .panel-group .panel-footer + .panel-collapse .panel-body { border-bottom: 1px solid #ddd; } .panel-default { border-color: #ddd; } .panel-default > .panel-heading { color: #333333; background-color: #f5f5f5; border-color: #ddd; } .panel-default > .panel-heading + .panel-collapse > .panel-body { border-top-color: #ddd; } .panel-default > .panel-heading .badge { color: #f5f5f5; background-color: #333333; } .panel-default > .panel-footer + .panel-collapse > .panel-body { border-bottom-color: #ddd; } .panel-primary { border-color: #337ab7; } .panel-primary > .panel-heading { color: #fff; background-color: #337ab7; border-color: #337ab7; } .panel-primary > .panel-heading + .panel-collapse > .panel-body { border-top-color: #337ab7; } .panel-primary > .panel-heading .badge { color: #337ab7; background-color: #fff; } .panel-primary > .panel-footer + .panel-collapse > .panel-body { border-bottom-color: #337ab7; } .panel-success { border-color: #d6e9c6; } .panel-success > .panel-heading { color: #3c763d; background-color: #dff0d8; border-color: #d6e9c6; } .panel-success > .panel-heading + .panel-collapse > .panel-body { border-top-color: #d6e9c6; } .panel-success > .panel-heading .badge { color: #dff0d8; background-color: #3c763d; } .panel-success > .panel-footer + .panel-collapse > .panel-body { border-bottom-color: #d6e9c6; } .panel-info { border-color: #bce8f1; } .panel-info > .panel-heading { color: #31708f; background-color: #d9edf7; border-color: #bce8f1; } .panel-info > .panel-heading + .panel-collapse > .panel-body { border-top-color: #bce8f1; } .panel-info > .panel-heading .badge { color: #d9edf7; background-color: #31708f; } .panel-info > .panel-footer + .panel-collapse > .panel-body { border-bottom-color: #bce8f1; } .panel-warning { border-color: #faebcc; } .panel-warning > .panel-heading { color: #8a6d3b; background-color: #fcf8e3; border-color: #faebcc; } .panel-warning > .panel-heading + .panel-collapse > .panel-body { border-top-color: #faebcc; } .panel-warning > .panel-heading .badge { color: #fcf8e3; background-color: #8a6d3b; } .panel-warning > .panel-footer + .panel-collapse > .panel-body { border-bottom-color: #faebcc; } .panel-danger { border-color: #ebccd1; } .panel-danger > .panel-heading { color: #a94442; background-color: #f2dede; border-color: #ebccd1; } .panel-danger > .panel-heading + .panel-collapse > .panel-body { border-top-color: #ebccd1; } .panel-danger > .panel-heading .badge { color: #f2dede; background-color: #a94442; } .panel-danger > .panel-footer + .panel-collapse > .panel-body { border-bottom-color: #ebccd1; } .embed-responsive { position: relative; display: block; height: 0; padding: 0; overflow: hidden; } .embed-responsive .embed-responsive-item, .embed-responsive iframe, .embed-responsive embed, .embed-responsive object, .embed-responsive video { position: absolute; top: 0; bottom: 0; left: 0; width: 100%; height: 100%; border: 0; } .embed-responsive-16by9 { padding-bottom: 56.25%; } .embed-responsive-4by3 { padding-bottom: 75%; } .well { min-height: 20px; padding: 19px; margin-bottom: 20px; background-color: #f5f5f5; border: 1px solid #e3e3e3; border-radius: 4px; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); } .well blockquote { border-color: #ddd; border-color: rgba(0, 0, 0, 0.15); } .well-lg { padding: 24px; border-radius: 6px; } .well-sm { padding: 9px; border-radius: 3px; } .close { float: right; font-size: 21px; font-weight: bold; line-height: 1; color: #000; text-shadow: 0 1px 0 #fff; filter: alpha(opacity=20); opacity: 0.2; } .close:hover, .close:focus { color: #000; text-decoration: none; cursor: pointer; filter: alpha(opacity=50); opacity: 0.5; } button.close { padding: 0; cursor: pointer; background: transparent; border: 0; -webkit-appearance: none; -moz-appearance: none; appearance: none; } .modal-open { overflow: hidden; } .modal { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 1050; display: none; overflow: hidden; -webkit-overflow-scrolling: touch; outline: 0; } .modal.fade .modal-dialog { -webkit-transform: translate(0, -25%); -ms-transform: translate(0, -25%); -o-transform: translate(0, -25%); transform: translate(0, -25%); -webkit-transition: -webkit-transform 0.3s ease-out; -o-transition: -o-transform 0.3s ease-out; transition: -webkit-transform 0.3s ease-out; transition: transform 0.3s ease-out; transition: transform 0.3s ease-out, -webkit-transform 0.3s ease-out, -o-transform 0.3s ease-out; } .modal.in .modal-dialog { -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); -o-transform: translate(0, 0); transform: translate(0, 0); } .modal-open .modal { overflow-x: hidden; overflow-y: auto; } .modal-dialog { position: relative; width: auto; margin: 10px; } .modal-content { position: relative; background-color: #fff; background-clip: padding-box; border: 1px solid #999; border: 1px solid rgba(0, 0, 0, 0.2); border-radius: 6px; -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); outline: 0; } .modal-backdrop { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 1040; background-color: #000; } .modal-backdrop.fade { filter: alpha(opacity=0); opacity: 0; } .modal-backdrop.in { filter: alpha(opacity=50); opacity: 0.5; } .modal-header { padding: 15px; border-bottom: 1px solid #e5e5e5; } .modal-header .close { margin-top: -2px; } .modal-title { margin: 0; line-height: 1.42857143; } .modal-body { position: relative; padding: 15px; } .modal-footer { padding: 15px; text-align: right; border-top: 1px solid #e5e5e5; } .modal-footer .btn + .btn { margin-bottom: 0; margin-left: 5px; } .modal-footer .btn-group .btn + .btn { margin-left: -1px; } .modal-footer .btn-block + .btn-block { margin-left: 0; } .modal-scrollbar-measure { position: absolute; top: -9999px; width: 50px; height: 50px; overflow: scroll; } @media (min-width: 768px) { .modal-dialog { width: 600px; margin: 30px auto; } .modal-content { -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); } .modal-sm { width: 300px; } } @media (min-width: 992px) { .modal-lg { width: 900px; } } .tooltip { position: absolute; z-index: 1070; display: block; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-style: normal; font-weight: 400; line-height: 1.42857143; line-break: auto; text-align: left; text-align: start; text-decoration: none; text-shadow: none; text-transform: none; letter-spacing: normal; word-break: normal; word-spacing: normal; word-wrap: normal; white-space: normal; font-size: 12px; filter: alpha(opacity=0); opacity: 0; } .tooltip.in { filter: alpha(opacity=90); opacity: 0.9; } .tooltip.top { padding: 5px 0; margin-top: -3px; } .tooltip.right { padding: 0 5px; margin-left: 3px; } .tooltip.bottom { padding: 5px 0; margin-top: 3px; } .tooltip.left { padding: 0 5px; margin-left: -3px; } .tooltip.top .tooltip-arrow { bottom: 0; left: 50%; margin-left: -5px; border-width: 5px 5px 0; border-top-color: #000; } .tooltip.top-left .tooltip-arrow { right: 5px; bottom: 0; margin-bottom: -5px; border-width: 5px 5px 0; border-top-color: #000; } .tooltip.top-right .tooltip-arrow { bottom: 0; left: 5px; margin-bottom: -5px; border-width: 5px 5px 0; border-top-color: #000; } .tooltip.right .tooltip-arrow { top: 50%; left: 0; margin-top: -5px; border-width: 5px 5px 5px 0; border-right-color: #000; } .tooltip.left .tooltip-arrow { top: 50%; right: 0; margin-top: -5px; border-width: 5px 0 5px 5px; border-left-color: #000; } .tooltip.bottom .tooltip-arrow { top: 0; left: 50%; margin-left: -5px; border-width: 0 5px 5px; border-bottom-color: #000; } .tooltip.bottom-left .tooltip-arrow { top: 0; right: 5px; margin-top: -5px; border-width: 0 5px 5px; border-bottom-color: #000; } .tooltip.bottom-right .tooltip-arrow { top: 0; left: 5px; margin-top: -5px; border-width: 0 5px 5px; border-bottom-color: #000; } .tooltip-inner { max-width: 200px; padding: 3px 8px; color: #fff; text-align: center; background-color: #000; border-radius: 4px; } .tooltip-arrow { position: absolute; width: 0; height: 0; border-color: transparent; border-style: solid; } .popover { position: absolute; top: 0; left: 0; z-index: 1060; display: none; max-width: 276px; padding: 1px; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-style: normal; font-weight: 400; line-height: 1.42857143; line-break: auto; text-align: left; text-align: start; text-decoration: none; text-shadow: none; text-transform: none; letter-spacing: normal; word-break: normal; word-spacing: normal; word-wrap: normal; white-space: normal; font-size: 14px; background-color: #fff; background-clip: padding-box; border: 1px solid #ccc; border: 1px solid rgba(0, 0, 0, 0.2); border-radius: 6px; -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); } .popover.top { margin-top: -10px; } .popover.right { margin-left: 10px; } .popover.bottom { margin-top: 10px; } .popover.left { margin-left: -10px; } .popover > .arrow { border-width: 11px; } .popover > .arrow, .popover > .arrow:after { position: absolute; display: block; width: 0; height: 0; border-color: transparent; border-style: solid; } .popover > .arrow:after { content: ""; border-width: 10px; } .popover.top > .arrow { bottom: -11px; left: 50%; margin-left: -11px; border-top-color: #999999; border-top-color: rgba(0, 0, 0, 0.25); border-bottom-width: 0; } .popover.top > .arrow:after { bottom: 1px; margin-left: -10px; content: " "; border-top-color: #fff; border-bottom-width: 0; } .popover.right > .arrow { top: 50%; left: -11px; margin-top: -11px; border-right-color: #999999; border-right-color: rgba(0, 0, 0, 0.25); border-left-width: 0; } .popover.right > .arrow:after { bottom: -10px; left: 1px; content: " "; border-right-color: #fff; border-left-width: 0; } .popover.bottom > .arrow { top: -11px; left: 50%; margin-left: -11px; border-top-width: 0; border-bottom-color: #999999; border-bottom-color: rgba(0, 0, 0, 0.25); } .popover.bottom > .arrow:after { top: 1px; margin-left: -10px; content: " "; border-top-width: 0; border-bottom-color: #fff; } .popover.left > .arrow { top: 50%; right: -11px; margin-top: -11px; border-right-width: 0; border-left-color: #999999; border-left-color: rgba(0, 0, 0, 0.25); } .popover.left > .arrow:after { right: 1px; bottom: -10px; content: " "; border-right-width: 0; border-left-color: #fff; } .popover-title { padding: 8px 14px; margin: 0; font-size: 14px; background-color: #f7f7f7; border-bottom: 1px solid #ebebeb; border-radius: 5px 5px 0 0; } .popover-content { padding: 9px 14px; } .carousel { position: relative; } .carousel-inner { position: relative; width: 100%; overflow: hidden; } .carousel-inner > .item { position: relative; display: none; -webkit-transition: 0.6s ease-in-out left; -o-transition: 0.6s ease-in-out left; transition: 0.6s ease-in-out left; } .carousel-inner > .item > img, .carousel-inner > .item > a > img { line-height: 1; } @media all and (transform-3d), (-webkit-transform-3d) { .carousel-inner > .item { -webkit-transition: -webkit-transform 0.6s ease-in-out; -o-transition: -o-transform 0.6s ease-in-out; transition: -webkit-transform 0.6s ease-in-out; transition: transform 0.6s ease-in-out; transition: transform 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out, -o-transform 0.6s ease-in-out; -webkit-backface-visibility: hidden; backface-visibility: hidden; -webkit-perspective: 1000px; perspective: 1000px; } .carousel-inner > .item.next, .carousel-inner > .item.active.right { -webkit-transform: translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0); left: 0; } .carousel-inner > .item.prev, .carousel-inner > .item.active.left { -webkit-transform: translate3d(-100%, 0, 0); transform: translate3d(-100%, 0, 0); left: 0; } .carousel-inner > .item.next.left, .carousel-inner > .item.prev.right, .carousel-inner > .item.active { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); left: 0; } } .carousel-inner > .active, .carousel-inner > .next, .carousel-inner > .prev { display: block; } .carousel-inner > .active { left: 0; } .carousel-inner > .next, .carousel-inner > .prev { position: absolute; top: 0; width: 100%; } .carousel-inner > .next { left: 100%; } .carousel-inner > .prev { left: -100%; } .carousel-inner > .next.left, .carousel-inner > .prev.right { left: 0; } .carousel-inner > .active.left { left: -100%; } .carousel-inner > .active.right { left: 100%; } .carousel-control { position: absolute; top: 0; bottom: 0; left: 0; width: 15%; font-size: 20px; color: #fff; text-align: center; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); background-color: rgba(0, 0, 0, 0); filter: alpha(opacity=50); opacity: 0.5; } .carousel-control.left { background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.0001))); background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); background-repeat: repeat-x; } .carousel-control.right { right: 0; left: auto; background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.0001)), to(rgba(0, 0, 0, 0.5))); background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); background-repeat: repeat-x; } .carousel-control:hover, .carousel-control:focus { color: #fff; text-decoration: none; outline: 0; filter: alpha(opacity=90); opacity: 0.9; } .carousel-control .icon-prev, .carousel-control .icon-next, .carousel-control .glyphicon-chevron-left, .carousel-control .glyphicon-chevron-right { position: absolute; top: 50%; z-index: 5; display: inline-block; margin-top: -10px; } .carousel-control .icon-prev, .carousel-control .glyphicon-chevron-left { left: 50%; margin-left: -10px; } .carousel-control .icon-next, .carousel-control .glyphicon-chevron-right { right: 50%; margin-right: -10px; } .carousel-control .icon-prev, .carousel-control .icon-next { width: 20px; height: 20px; font-family: serif; line-height: 1; } .carousel-control .icon-prev:before { content: "\2039"; } .carousel-control .icon-next:before { content: "\203a"; } .carousel-indicators { position: absolute; bottom: 10px; left: 50%; z-index: 15; width: 60%; padding-left: 0; margin-left: -30%; text-align: center; list-style: none; } .carousel-indicators li { display: inline-block; width: 10px; height: 10px; margin: 1px; text-indent: -999px; cursor: pointer; background-color: #000 \9; background-color: rgba(0, 0, 0, 0); border: 1px solid #fff; border-radius: 10px; } .carousel-indicators .active { width: 12px; height: 12px; margin: 0; background-color: #fff; } .carousel-caption { position: absolute; right: 15%; bottom: 20px; left: 15%; z-index: 10; padding-top: 20px; padding-bottom: 20px; color: #fff; text-align: center; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); } .carousel-caption .btn { text-shadow: none; } @media screen and (min-width: 768px) { .carousel-control .glyphicon-chevron-left, .carousel-control .glyphicon-chevron-right, .carousel-control .icon-prev, .carousel-control .icon-next { width: 30px; height: 30px; margin-top: -10px; font-size: 30px; } .carousel-control .glyphicon-chevron-left, .carousel-control .icon-prev { margin-left: -10px; } .carousel-control .glyphicon-chevron-right, .carousel-control .icon-next { margin-right: -10px; } .carousel-caption { right: 20%; left: 20%; padding-bottom: 30px; } .carousel-indicators { bottom: 20px; } } .clearfix:before, .clearfix:after, .dl-horizontal dd:before, .dl-horizontal dd:after, .container:before, .container:after, .container-fluid:before, .container-fluid:after, .row:before, .row:after, .form-horizontal .form-group:before, .form-horizontal .form-group:after, .btn-toolbar:before, .btn-toolbar:after, .btn-group-vertical > .btn-group:before, .btn-group-vertical > .btn-group:after, .nav:before, .nav:after, .navbar:before, .navbar:after, .navbar-header:before, .navbar-header:after, .navbar-collapse:before, .navbar-collapse:after, .pager:before, .pager:after, .panel-body:before, .panel-body:after, .modal-header:before, .modal-header:after, .modal-footer:before, .modal-footer:after { display: table; content: " "; } .clearfix:after, .dl-horizontal dd:after, .container:after, .container-fluid:after, .row:after, .form-horizontal .form-group:after, .btn-toolbar:after, .btn-group-vertical > .btn-group:after, .nav:after, .navbar:after, .navbar-header:after, .navbar-collapse:after, .pager:after, .panel-body:after, .modal-header:after, .modal-footer:after { clear: both; } .center-block { display: block; margin-right: auto; margin-left: auto; } .pull-right { float: right !important; } .pull-left { float: left !important; } .hide { display: none !important; } .show { display: block !important; } .invisible { visibility: hidden; } .text-hide { font: 0/0 a; color: transparent; text-shadow: none; background-color: transparent; border: 0; } .hidden { display: none !important; } .affix { position: fixed; } @-ms-viewport { width: device-width; } .visible-xs, .visible-sm, .visible-md, .visible-lg { display: none !important; } .visible-xs-block, .visible-xs-inline, .visible-xs-inline-block, .visible-sm-block, .visible-sm-inline, .visible-sm-inline-block, .visible-md-block, .visible-md-inline, .visible-md-inline-block, .visible-lg-block, .visible-lg-inline, .visible-lg-inline-block { display: none !important; } @media (max-width: 767px) { .visible-xs { display: block !important; } table.visible-xs { display: table !important; } tr.visible-xs { display: table-row !important; } th.visible-xs, td.visible-xs { display: table-cell !important; } } @media (max-width: 767px) { .visible-xs-block { display: block !important; } } @media (max-width: 767px) { .visible-xs-inline { display: inline !important; } } @media (max-width: 767px) { .visible-xs-inline-block { display: inline-block !important; } } @media (min-width: 768px) and (max-width: 991px) { .visible-sm { display: block !important; } table.visible-sm { display: table !important; } tr.visible-sm { display: table-row !important; } th.visible-sm, td.visible-sm { display: table-cell !important; } } @media (min-width: 768px) and (max-width: 991px) { .visible-sm-block { display: block !important; } } @media (min-width: 768px) and (max-width: 991px) { .visible-sm-inline { display: inline !important; } } @media (min-width: 768px) and (max-width: 991px) { .visible-sm-inline-block { display: inline-block !important; } } @media (min-width: 992px) and (max-width: 1199px) { .visible-md { display: block !important; } table.visible-md { display: table !important; } tr.visible-md { display: table-row !important; } th.visible-md, td.visible-md { display: table-cell !important; } } @media (min-width: 992px) and (max-width: 1199px) { .visible-md-block { display: block !important; } } @media (min-width: 992px) and (max-width: 1199px) { .visible-md-inline { display: inline !important; } } @media (min-width: 992px) and (max-width: 1199px) { .visible-md-inline-block { display: inline-block !important; } } @media (min-width: 1200px) { .visible-lg { display: block !important; } table.visible-lg { display: table !important; } tr.visible-lg { display: table-row !important; } th.visible-lg, td.visible-lg { display: table-cell !important; } } @media (min-width: 1200px) { .visible-lg-block { display: block !important; } } @media (min-width: 1200px) { .visible-lg-inline { display: inline !important; } } @media (min-width: 1200px) { .visible-lg-inline-block { display: inline-block !important; } } @media (max-width: 767px) { .hidden-xs { display: none !important; } } @media (min-width: 768px) and (max-width: 991px) { .hidden-sm { display: none !important; } } @media (min-width: 992px) and (max-width: 1199px) { .hidden-md { display: none !important; } } @media (min-width: 1200px) { .hidden-lg { display: none !important; } } .visible-print { display: none !important; } @media print { .visible-print { display: block !important; } table.visible-print { display: table !important; } tr.visible-print { display: table-row !important; } th.visible-print, td.visible-print { display: table-cell !important; } } .visible-print-block { display: none !important; } @media print { .visible-print-block { display: block !important; } } .visible-print-inline { display: none !important; } @media print { .visible-print-inline { display: inline !important; } } .visible-print-inline-block { display: none !important; } @media print { .visible-print-inline-block { display: inline-block !important; } } @media print { .hidden-print { display: none !important; } } /*# sourceMappingURL=bootstrap.css.map */ ================================================ FILE: doc/css/site.css ================================================ .urubu { background-image: url("../img/urubu_cover.png"); background-size: cover; color: white; } body { position: relative; padding-top: 50px; padding-bottom: 20px; } .page-header { margin-top: 30px; } .breadcrumb { margin-top: 20px; } .content h2:first-of-type { margin-top: 0px; } .half-rule { width: 100px; margin: 25px auto; } .fa { margin-right: 0.5em; } .checklist { padding: 0; list-style: none; } /* footer */ .footer { margin-top: 30px; padding-top: 16px; color: #777; border-top: 1px solid #eee; font-size: 90%; text-align: center; } .footer p { margin: 0px; } /* toc */ .sidebar { font-size: 90%; line-height: normal } .toc ul { padding-left: 0; list-style: none; } .toc ul li { padding-top: 3px; } .toc ul ul { padding-left: 10px; font-size: 95%; } /* heading scrolling */ h2[id]:before, h3[id]:before{ content: ""; display: block; height: 70px; margin-top:-70px; } /* affix hacks from boostrap 3.0 docs */ .sidebar.affix { position: static; } @media (min-width: 992px) { /* Widen the fixed sidebar */ .sidebar.affix, .sidebar.affix-bottom { width: 213px; } .sidebar.affix { position: fixed; /* Undo the static from mobile first approach */ top: 80px; } .sidebar.affix-bottom { position: absolute; /* Undo the static from mobile first approach */ } } @media (min-width: 1200px) { /* Widen the fixed sidebar again */ .sidebar.affix, .sidebar.affix-bottom { width: 263px; } } ================================================ FILE: doc/css/syntax.css ================================================ .codehilite { background: #ffffff; } .codehilite .c { color: #999988; font-style: italic } /* Comment */ .codehilite .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .codehilite .k { font-weight: bold } /* Keyword */ .codehilite .o { font-weight: bold } /* Operator */ .codehilite .cm { color: #999988; font-style: italic } /* Comment.Multiline */ .codehilite .cp { color: #999999; font-weight: bold } /* Comment.Preproc */ .codehilite .c1 { color: #999988; font-style: italic } /* Comment.Single */ .codehilite .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */ .codehilite .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .codehilite .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */ .codehilite .ge { font-style: italic } /* Generic.Emph */ .codehilite .gr { color: #aa0000 } /* Generic.Error */ .codehilite .gh { color: #999999 } /* Generic.Heading */ .codehilite .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .codehilite .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */ .codehilite .go { color: #888888 } /* Generic.Output */ .codehilite .gp { color: #555555 } /* Generic.Prompt */ .codehilite .gs { font-weight: bold } /* Generic.Strong */ .codehilite .gu { color: #aaaaaa } /* Generic.Subheading */ .codehilite .gt { color: #aa0000 } /* Generic.Traceback */ .codehilite .kc { font-weight: bold } /* Keyword.Constant */ .codehilite .kd { font-weight: bold } /* Keyword.Declaration */ .codehilite .kp { font-weight: bold } /* Keyword.Pseudo */ .codehilite .kr { font-weight: bold } /* Keyword.Reserved */ .codehilite .kt { color: #445588; font-weight: bold } /* Keyword.Type */ .codehilite .m { color: #009999 } /* Literal.Number */ .codehilite .s { color: #d14 } /* Literal.String */ .codehilite .na { color: #008080 } /* Name.Attribute */ .codehilite .nb { color: #0086B3 } /* Name.Builtin */ .codehilite .nc { color: #445588; font-weight: bold } /* Name.Class */ .codehilite .no { color: #008080 } /* Name.Constant */ .codehilite .ni { color: #800080 } /* Name.Entity */ .codehilite .ne { color: #990000; font-weight: bold } /* Name.Exception */ .codehilite .nf { color: #990000; font-weight: bold } /* Name.Function */ .codehilite .nn { color: #555555 } /* Name.Namespace */ .codehilite .nt { color: #000080 } /* Name.Tag */ .codehilite .nv { color: #008080 } /* Name.Variable */ .codehilite .ow { font-weight: bold } /* Operator.Word */ .codehilite .w { color: #bbbbbb } /* Text.Whitespace */ .codehilite .mf { color: #009999 } /* Literal.Number.Float */ .codehilite .mh { color: #009999 } /* Literal.Number.Hex */ .codehilite .mi { color: #009999 } /* Literal.Number.Integer */ .codehilite .mo { color: #009999 } /* Literal.Number.Oct */ .codehilite .sb { color: #d14 } /* Literal.String.Backtick */ .codehilite .sc { color: #d14 } /* Literal.String.Char */ .codehilite .sd { color: #d14 } /* Literal.String.Doc */ .codehilite .s2 { color: #d14 } /* Literal.String.Double */ .codehilite .se { color: #d14 } /* Literal.String.Escape */ .codehilite .sh { color: #d14 } /* Literal.String.Heredoc */ .codehilite .si { color: #d14 } /* Literal.String.Interpol */ .codehilite .sx { color: #d14 } /* Literal.String.Other */ .codehilite .sr { color: #009926 } /* Literal.String.Regex */ .codehilite .s1 { color: #d14 } /* Literal.String.Single */ .codehilite .ss { color: #990073 } /* Literal.String.Symbol */ .codehilite .bp { color: #999999 } /* Name.Builtin.Pseudo */ .codehilite .vc { color: #008080 } /* Name.Variable.Class */ .codehilite .vg { color: #008080 } /* Name.Variable.Global */ .codehilite .vi { color: #008080 } /* Name.Variable.Instance */ .codehilite .il { color: #009999 } /* Literal.Number.Integer.Long */ ================================================ FILE: doc/faq/baseurl-preview.md ================================================ --- title: How to preview sites that use the baseurl option? layout: page date: 2015-04-30 --- Urubu version 0.8 and higher ---------------------------- The `urubu serve` command takes the `baseurl` setting automatically into account. Urubu version 0.7 ------------------ The `urubu serve` server does not include the `baseurl` prefix when serving pages so sites that use `baseurl` can't be previewed locally using `urubu serve`. An alternative option is to use [tservice](https://github.com/jiffyclub/tservice), which includes an option to serve a local static site with a URL prefix. To use tservice with an Urubu site instead of using `urubu serve` call `tserve` with the prefix option, e.g. ``` tserve --prefix _build ``` Where `` is your site's particular prefix. ================================================ FILE: doc/faq/formulas.md ================================================ --- title: Is there a way to render formulas? date: 2015-08-08 --- Yes: you can easily use MathJax with Urubu. Read more about it [here](http://www.jandecaluwe.com/blog/urubu-formulas.html). ================================================ FILE: doc/faq/index.md ================================================ --- title: FAQ order: date --- ================================================ FILE: doc/faq/licensing-requirements.md ================================================ --- title: What are the licensing requirements? layout: page date: 2014-01-12 --- Urubu is licensed under the [software_license]. The first thing to understand is that this license applies only to the Urubu software. It has no implications on website projects managed with Urubu. You are free to license your projects in any way you choose. The license only becomes relevant when you release a modified version of the Urubu software to the public in some way. In that case, you have to release the modified source code also, under the same license. With the original GPL, a release meant shipping software to user that would install and run it locally. However, these days software is often made available by running it on a server. Under the original GPL, there would be no requirement to release the modified source code in such as case. This clearly violates the spirit of the GNU Licenses. The [software_license] fixes that problem. If you make the modified software available by running it on a server, you have to make the modified source code available to the users under the same license. ================================================ FILE: doc/faq/link2section.md ================================================ --- title: Can I specify a link to a section in a page? layout: page date: 2015-08-07 --- Yes, Urubu support links to page sections. Read [this blog post](http://www.jandecaluwe.com/blog/urubu-0-6.html) to learn how. ================================================ FILE: doc/faq/media-files.md ================================================ --- title: How to add media files? layout: page date: 2014-09-11 --- The source structure of a project is preserved in the built website, and all non-markdown content files are copied verbatim. See [/manual/structure]. Therefore, you can put media files at any convenient place in the source, and refer to them using Markdown image syntax, with a relative or root-relative path to the source file. ================================================ FILE: doc/faq/sitemap.md ================================================ --- title: How do I make a sitemap? layout: page date: 2016-07-04 --- To generate a sitemap you need to do the following: * Create a markdown file called `sitemap.md` like this: ``` --- title: sitemap layout: sitemap changefreq: monthly priority: 1.0 xmlns: http://www.google.com/schemas/sitemap/0.84 saveas: sitemap.xml --- ``` * Provide a `sitemap.html` in the `_layouts` directory, with looking something like the following: ``` {% raw %} {% for t in site.reflinks %} {% if site.reflinks[t].fn and not site.reflinks[t].hidden %} {{ site.hostname }}{{ site.reflinks[t].url }} {{ this.changefreq }} {{ this.priority }} {% endif %} {% endfor %} {% endraw %} ``` What makes this work is for the main part the `saveas` parameter in the `sitemap.md` file, which overrides the default output filename with `sitemap.xml` instead of `sitemap.html`. If you add other sitemaps don't forget to specify distinct `id` and `saveas` for each one, to prevent `Ambiguous reference id` errors. ================================================ FILE: doc/faq/tags.md ================================================ --- title: How to use tags? layout: page date: 2015-12-05 --- Urubu supports tags. To use them, you need 2 things: * Assign the desired tags to content pages, by assigning a tag or a list of tags to the `tags` attribute. See also: [/manual/structure#Content files]. * Provide a `tag.html` layout in the `_layouts` directory. It is the existence of the `tag.html` layout that triggers the generation of tag-related content. For example, if you have used tags `bar` and `foo` in the project, you will see that the `_build` folder contains `tag/bar/index.html` and `tag/foo/index.html`. Those index files use the `tag.html` layout to show the content related to a tag. Presumably, there is already a general `index.html` layout to show content in a folder. An initial `tag.html` layout can then be a one-liner by using template inheritance, like so: ``` {% raw %} {% extends "index.html" %} {% endraw %} ``` Of course, you may want to specialize the `tag.html` layout further to better reflect the purpose. Urubu also generates the corresponding tag objects so that you can use them in your layouts. This is described in [/manual/templates#Tag objects]. Note that the `_build` will contain a top-level `tag` folder, even when the source directory does not. Optionally, you can define the `tag` folder in the source also. You can then define an index file and set attributes such as the `layout` to display the tags themselves. However, the content will be generated by Urubu automatically and needs not be set. See also: [/manual/templates#Tag folder object]. ================================================ FILE: doc/index.md ================================================ --- title: Urubu layout: home content: - start - manual - ref: urubu-quickstart title: Quickstart - faq - more tagline: A micro CMS for static websites ---

For websites, not just blogs

Set up a website as logically related content. Content ordering is flexible, not just by date.

Focus on navigation

Easily set up a navbar, a table of contents sidebar, breadcrumbs and pagers.

Ready for Bootstrap

Urubu plays well with Bootstrap, the popular framework for great looking websites.

Markdown content

Enter content in light-weight Markdown syntax, with popular extensions.

Wiki links

Easily refer to other pages like in wikis, using Markdown syntax.

Powerful templating

Use the powerful Jinja2 templating library to define page layouts.

Sophisticated control

Per-page control of page layout and other stuff. Plus user-defined variables.

Python power

Urubu is built with Python. It provides Python hooks to assist in templating.

Ideal with git

Use a git workflow to develop your website. Deploy by pushing.


And of course, it's open source!

================================================ FILE: doc/js/bootstrap.js ================================================ /*! * Bootstrap v3.4.1 (https://getbootstrap.com/) * Copyright 2011-2019 Twitter, Inc. * Licensed under the MIT license */ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript requires jQuery') } +function ($) { 'use strict'; var version = $.fn.jquery.split(' ')[0].split('.') if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) { throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4') } }(jQuery); /* ======================================================================== * Bootstrap: transition.js v3.4.1 * https://getbootstrap.com/docs/3.4/javascript/#transitions * ======================================================================== * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // CSS TRANSITION SUPPORT (Shoutout: https://modernizr.com/) // ============================================================ function transitionEnd() { var el = document.createElement('bootstrap') var transEndEventNames = { WebkitTransition : 'webkitTransitionEnd', MozTransition : 'transitionend', OTransition : 'oTransitionEnd otransitionend', transition : 'transitionend' } for (var name in transEndEventNames) { if (el.style[name] !== undefined) { return { end: transEndEventNames[name] } } } return false // explicit for ie8 ( ._.) } // https://blog.alexmaccaw.com/css-transitions $.fn.emulateTransitionEnd = function (duration) { var called = false var $el = this $(this).one('bsTransitionEnd', function () { called = true }) var callback = function () { if (!called) $($el).trigger($.support.transition.end) } setTimeout(callback, duration) return this } $(function () { $.support.transition = transitionEnd() if (!$.support.transition) return $.event.special.bsTransitionEnd = { bindType: $.support.transition.end, delegateType: $.support.transition.end, handle: function (e) { if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments) } } }) }(jQuery); /* ======================================================================== * Bootstrap: alert.js v3.4.1 * https://getbootstrap.com/docs/3.4/javascript/#alerts * ======================================================================== * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // ALERT CLASS DEFINITION // ====================== var dismiss = '[data-dismiss="alert"]' var Alert = function (el) { $(el).on('click', dismiss, this.close) } Alert.VERSION = '3.4.1' Alert.TRANSITION_DURATION = 150 Alert.prototype.close = function (e) { var $this = $(this) var selector = $this.attr('data-target') if (!selector) { selector = $this.attr('href') selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 } selector = selector === '#' ? [] : selector var $parent = $(document).find(selector) if (e) e.preventDefault() if (!$parent.length) { $parent = $this.closest('.alert') } $parent.trigger(e = $.Event('close.bs.alert')) if (e.isDefaultPrevented()) return $parent.removeClass('in') function removeElement() { // detach from parent, fire event then clean up data $parent.detach().trigger('closed.bs.alert').remove() } $.support.transition && $parent.hasClass('fade') ? $parent .one('bsTransitionEnd', removeElement) .emulateTransitionEnd(Alert.TRANSITION_DURATION) : removeElement() } // ALERT PLUGIN DEFINITION // ======================= function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.alert') if (!data) $this.data('bs.alert', (data = new Alert(this))) if (typeof option == 'string') data[option].call($this) }) } var old = $.fn.alert $.fn.alert = Plugin $.fn.alert.Constructor = Alert // ALERT NO CONFLICT // ================= $.fn.alert.noConflict = function () { $.fn.alert = old return this } // ALERT DATA-API // ============== $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) }(jQuery); /* ======================================================================== * Bootstrap: button.js v3.4.1 * https://getbootstrap.com/docs/3.4/javascript/#buttons * ======================================================================== * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // BUTTON PUBLIC CLASS DEFINITION // ============================== var Button = function (element, options) { this.$element = $(element) this.options = $.extend({}, Button.DEFAULTS, options) this.isLoading = false } Button.VERSION = '3.4.1' Button.DEFAULTS = { loadingText: 'loading...' } Button.prototype.setState = function (state) { var d = 'disabled' var $el = this.$element var val = $el.is('input') ? 'val' : 'html' var data = $el.data() state += 'Text' if (data.resetText == null) $el.data('resetText', $el[val]()) // push to event loop to allow forms to submit setTimeout($.proxy(function () { $el[val](data[state] == null ? this.options[state] : data[state]) if (state == 'loadingText') { this.isLoading = true $el.addClass(d).attr(d, d).prop(d, true) } else if (this.isLoading) { this.isLoading = false $el.removeClass(d).removeAttr(d).prop(d, false) } }, this), 0) } Button.prototype.toggle = function () { var changed = true var $parent = this.$element.closest('[data-toggle="buttons"]') if ($parent.length) { var $input = this.$element.find('input') if ($input.prop('type') == 'radio') { if ($input.prop('checked')) changed = false $parent.find('.active').removeClass('active') this.$element.addClass('active') } else if ($input.prop('type') == 'checkbox') { if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false this.$element.toggleClass('active') } $input.prop('checked', this.$element.hasClass('active')) if (changed) $input.trigger('change') } else { this.$element.attr('aria-pressed', !this.$element.hasClass('active')) this.$element.toggleClass('active') } } // BUTTON PLUGIN DEFINITION // ======================== function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.button') var options = typeof option == 'object' && option if (!data) $this.data('bs.button', (data = new Button(this, options))) if (option == 'toggle') data.toggle() else if (option) data.setState(option) }) } var old = $.fn.button $.fn.button = Plugin $.fn.button.Constructor = Button // BUTTON NO CONFLICT // ================== $.fn.button.noConflict = function () { $.fn.button = old return this } // BUTTON DATA-API // =============== $(document) .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) { var $btn = $(e.target).closest('.btn') Plugin.call($btn, 'toggle') if (!($(e.target).is('input[type="radio"], input[type="checkbox"]'))) { // Prevent double click on radios, and the double selections (so cancellation) on checkboxes e.preventDefault() // The target component still receive the focus if ($btn.is('input,button')) $btn.trigger('focus') else $btn.find('input:visible,button:visible').first().trigger('focus') } }) .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) { $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type)) }) }(jQuery); /* ======================================================================== * Bootstrap: carousel.js v3.4.1 * https://getbootstrap.com/docs/3.4/javascript/#carousel * ======================================================================== * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // CAROUSEL CLASS DEFINITION // ========================= var Carousel = function (element, options) { this.$element = $(element) this.$indicators = this.$element.find('.carousel-indicators') this.options = options this.paused = null this.sliding = null this.interval = null this.$active = null this.$items = null this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this)) this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element .on('mouseenter.bs.carousel', $.proxy(this.pause, this)) .on('mouseleave.bs.carousel', $.proxy(this.cycle, this)) } Carousel.VERSION = '3.4.1' Carousel.TRANSITION_DURATION = 600 Carousel.DEFAULTS = { interval: 5000, pause: 'hover', wrap: true, keyboard: true } Carousel.prototype.keydown = function (e) { if (/input|textarea/i.test(e.target.tagName)) return switch (e.which) { case 37: this.prev(); break case 39: this.next(); break default: return } e.preventDefault() } Carousel.prototype.cycle = function (e) { e || (this.paused = false) this.interval && clearInterval(this.interval) this.options.interval && !this.paused && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) return this } Carousel.prototype.getItemIndex = function (item) { this.$items = item.parent().children('.item') return this.$items.index(item || this.$active) } Carousel.prototype.getItemForDirection = function (direction, active) { var activeIndex = this.getItemIndex(active) var willWrap = (direction == 'prev' && activeIndex === 0) || (direction == 'next' && activeIndex == (this.$items.length - 1)) if (willWrap && !this.options.wrap) return active var delta = direction == 'prev' ? -1 : 1 var itemIndex = (activeIndex + delta) % this.$items.length return this.$items.eq(itemIndex) } Carousel.prototype.to = function (pos) { var that = this var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active')) if (pos > (this.$items.length - 1) || pos < 0) return if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid" if (activeIndex == pos) return this.pause().cycle() return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos)) } Carousel.prototype.pause = function (e) { e || (this.paused = true) if (this.$element.find('.next, .prev').length && $.support.transition) { this.$element.trigger($.support.transition.end) this.cycle(true) } this.interval = clearInterval(this.interval) return this } Carousel.prototype.next = function () { if (this.sliding) return return this.slide('next') } Carousel.prototype.prev = function () { if (this.sliding) return return this.slide('prev') } Carousel.prototype.slide = function (type, next) { var $active = this.$element.find('.item.active') var $next = next || this.getItemForDirection(type, $active) var isCycling = this.interval var direction = type == 'next' ? 'left' : 'right' var that = this if ($next.hasClass('active')) return (this.sliding = false) var relatedTarget = $next[0] var slideEvent = $.Event('slide.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) this.$element.trigger(slideEvent) if (slideEvent.isDefaultPrevented()) return this.sliding = true isCycling && this.pause() if (this.$indicators.length) { this.$indicators.find('.active').removeClass('active') var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)]) $nextIndicator && $nextIndicator.addClass('active') } var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid" if ($.support.transition && this.$element.hasClass('slide')) { $next.addClass(type) if (typeof $next === 'object' && $next.length) { $next[0].offsetWidth // force reflow } $active.addClass(direction) $next.addClass(direction) $active .one('bsTransitionEnd', function () { $next.removeClass([type, direction].join(' ')).addClass('active') $active.removeClass(['active', direction].join(' ')) that.sliding = false setTimeout(function () { that.$element.trigger(slidEvent) }, 0) }) .emulateTransitionEnd(Carousel.TRANSITION_DURATION) } else { $active.removeClass('active') $next.addClass('active') this.sliding = false this.$element.trigger(slidEvent) } isCycling && this.cycle() return this } // CAROUSEL PLUGIN DEFINITION // ========================== function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.carousel') var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) var action = typeof option == 'string' ? option : options.slide if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) if (typeof option == 'number') data.to(option) else if (action) data[action]() else if (options.interval) data.pause().cycle() }) } var old = $.fn.carousel $.fn.carousel = Plugin $.fn.carousel.Constructor = Carousel // CAROUSEL NO CONFLICT // ==================== $.fn.carousel.noConflict = function () { $.fn.carousel = old return this } // CAROUSEL DATA-API // ================= var clickHandler = function (e) { var $this = $(this) var href = $this.attr('href') if (href) { href = href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 } var target = $this.attr('data-target') || href var $target = $(document).find(target) if (!$target.hasClass('carousel')) return var options = $.extend({}, $target.data(), $this.data()) var slideIndex = $this.attr('data-slide-to') if (slideIndex) options.interval = false Plugin.call($target, options) if (slideIndex) { $target.data('bs.carousel').to(slideIndex) } e.preventDefault() } $(document) .on('click.bs.carousel.data-api', '[data-slide]', clickHandler) .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler) $(window).on('load', function () { $('[data-ride="carousel"]').each(function () { var $carousel = $(this) Plugin.call($carousel, $carousel.data()) }) }) }(jQuery); /* ======================================================================== * Bootstrap: collapse.js v3.4.1 * https://getbootstrap.com/docs/3.4/javascript/#collapse * ======================================================================== * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ /* jshint latedef: false */ +function ($) { 'use strict'; // COLLAPSE PUBLIC CLASS DEFINITION // ================================ var Collapse = function (element, options) { this.$element = $(element) this.options = $.extend({}, Collapse.DEFAULTS, options) this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' + '[data-toggle="collapse"][data-target="#' + element.id + '"]') this.transitioning = null if (this.options.parent) { this.$parent = this.getParent() } else { this.addAriaAndCollapsedClass(this.$element, this.$trigger) } if (this.options.toggle) this.toggle() } Collapse.VERSION = '3.4.1' Collapse.TRANSITION_DURATION = 350 Collapse.DEFAULTS = { toggle: true } Collapse.prototype.dimension = function () { var hasWidth = this.$element.hasClass('width') return hasWidth ? 'width' : 'height' } Collapse.prototype.show = function () { if (this.transitioning || this.$element.hasClass('in')) return var activesData var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing') if (actives && actives.length) { activesData = actives.data('bs.collapse') if (activesData && activesData.transitioning) return } var startEvent = $.Event('show.bs.collapse') this.$element.trigger(startEvent) if (startEvent.isDefaultPrevented()) return if (actives && actives.length) { Plugin.call(actives, 'hide') activesData || actives.data('bs.collapse', null) } var dimension = this.dimension() this.$element .removeClass('collapse') .addClass('collapsing')[dimension](0) .attr('aria-expanded', true) this.$trigger .removeClass('collapsed') .attr('aria-expanded', true) this.transitioning = 1 var complete = function () { this.$element .removeClass('collapsing') .addClass('collapse in')[dimension]('') this.transitioning = 0 this.$element .trigger('shown.bs.collapse') } if (!$.support.transition) return complete.call(this) var scrollSize = $.camelCase(['scroll', dimension].join('-')) this.$element .one('bsTransitionEnd', $.proxy(complete, this)) .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize]) } Collapse.prototype.hide = function () { if (this.transitioning || !this.$element.hasClass('in')) return var startEvent = $.Event('hide.bs.collapse') this.$element.trigger(startEvent) if (startEvent.isDefaultPrevented()) return var dimension = this.dimension() this.$element[dimension](this.$element[dimension]())[0].offsetHeight this.$element .addClass('collapsing') .removeClass('collapse in') .attr('aria-expanded', false) this.$trigger .addClass('collapsed') .attr('aria-expanded', false) this.transitioning = 1 var complete = function () { this.transitioning = 0 this.$element .removeClass('collapsing') .addClass('collapse') .trigger('hidden.bs.collapse') } if (!$.support.transition) return complete.call(this) this.$element [dimension](0) .one('bsTransitionEnd', $.proxy(complete, this)) .emulateTransitionEnd(Collapse.TRANSITION_DURATION) } Collapse.prototype.toggle = function () { this[this.$element.hasClass('in') ? 'hide' : 'show']() } Collapse.prototype.getParent = function () { return $(document).find(this.options.parent) .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]') .each($.proxy(function (i, element) { var $element = $(element) this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element) }, this)) .end() } Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) { var isOpen = $element.hasClass('in') $element.attr('aria-expanded', isOpen) $trigger .toggleClass('collapsed', !isOpen) .attr('aria-expanded', isOpen) } function getTargetFromTrigger($trigger) { var href var target = $trigger.attr('data-target') || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 return $(document).find(target) } // COLLAPSE PLUGIN DEFINITION // ========================== function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.collapse') var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) if (typeof option == 'string') data[option]() }) } var old = $.fn.collapse $.fn.collapse = Plugin $.fn.collapse.Constructor = Collapse // COLLAPSE NO CONFLICT // ==================== $.fn.collapse.noConflict = function () { $.fn.collapse = old return this } // COLLAPSE DATA-API // ================= $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { var $this = $(this) if (!$this.attr('data-target')) e.preventDefault() var $target = getTargetFromTrigger($this) var data = $target.data('bs.collapse') var option = data ? 'toggle' : $this.data() Plugin.call($target, option) }) }(jQuery); /* ======================================================================== * Bootstrap: dropdown.js v3.4.1 * https://getbootstrap.com/docs/3.4/javascript/#dropdowns * ======================================================================== * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // DROPDOWN CLASS DEFINITION // ========================= var backdrop = '.dropdown-backdrop' var toggle = '[data-toggle="dropdown"]' var Dropdown = function (element) { $(element).on('click.bs.dropdown', this.toggle) } Dropdown.VERSION = '3.4.1' function getParent($this) { var selector = $this.attr('data-target') if (!selector) { selector = $this.attr('href') selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 } var $parent = selector !== '#' ? $(document).find(selector) : null return $parent && $parent.length ? $parent : $this.parent() } function clearMenus(e) { if (e && e.which === 3) return $(backdrop).remove() $(toggle).each(function () { var $this = $(this) var $parent = getParent($this) var relatedTarget = { relatedTarget: this } if (!$parent.hasClass('open')) return if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget)) if (e.isDefaultPrevented()) return $this.attr('aria-expanded', 'false') $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget)) }) } Dropdown.prototype.toggle = function (e) { var $this = $(this) if ($this.is('.disabled, :disabled')) return var $parent = getParent($this) var isActive = $parent.hasClass('open') clearMenus() if (!isActive) { if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { // if mobile we use a backdrop because click events don't delegate $(document.createElement('div')) .addClass('dropdown-backdrop') .insertAfter($(this)) .on('click', clearMenus) } var relatedTarget = { relatedTarget: this } $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget)) if (e.isDefaultPrevented()) return $this .trigger('focus') .attr('aria-expanded', 'true') $parent .toggleClass('open') .trigger($.Event('shown.bs.dropdown', relatedTarget)) } return false } Dropdown.prototype.keydown = function (e) { if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return var $this = $(this) e.preventDefault() e.stopPropagation() if ($this.is('.disabled, :disabled')) return var $parent = getParent($this) var isActive = $parent.hasClass('open') if (!isActive && e.which != 27 || isActive && e.which == 27) { if (e.which == 27) $parent.find(toggle).trigger('focus') return $this.trigger('click') } var desc = ' li:not(.disabled):visible a' var $items = $parent.find('.dropdown-menu' + desc) if (!$items.length) return var index = $items.index(e.target) if (e.which == 38 && index > 0) index-- // up if (e.which == 40 && index < $items.length - 1) index++ // down if (!~index) index = 0 $items.eq(index).trigger('focus') } // DROPDOWN PLUGIN DEFINITION // ========================== function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.dropdown') if (!data) $this.data('bs.dropdown', (data = new Dropdown(this))) if (typeof option == 'string') data[option].call($this) }) } var old = $.fn.dropdown $.fn.dropdown = Plugin $.fn.dropdown.Constructor = Dropdown // DROPDOWN NO CONFLICT // ==================== $.fn.dropdown.noConflict = function () { $.fn.dropdown = old return this } // APPLY TO STANDARD DROPDOWN ELEMENTS // =================================== $(document) .on('click.bs.dropdown.data-api', clearMenus) .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown) .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown) }(jQuery); /* ======================================================================== * Bootstrap: modal.js v3.4.1 * https://getbootstrap.com/docs/3.4/javascript/#modals * ======================================================================== * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // MODAL CLASS DEFINITION // ====================== var Modal = function (element, options) { this.options = options this.$body = $(document.body) this.$element = $(element) this.$dialog = this.$element.find('.modal-dialog') this.$backdrop = null this.isShown = null this.originalBodyPad = null this.scrollbarWidth = 0 this.ignoreBackdropClick = false this.fixedContent = '.navbar-fixed-top, .navbar-fixed-bottom' if (this.options.remote) { this.$element .find('.modal-content') .load(this.options.remote, $.proxy(function () { this.$element.trigger('loaded.bs.modal') }, this)) } } Modal.VERSION = '3.4.1' Modal.TRANSITION_DURATION = 300 Modal.BACKDROP_TRANSITION_DURATION = 150 Modal.DEFAULTS = { backdrop: true, keyboard: true, show: true } Modal.prototype.toggle = function (_relatedTarget) { return this.isShown ? this.hide() : this.show(_relatedTarget) } Modal.prototype.show = function (_relatedTarget) { var that = this var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget }) this.$element.trigger(e) if (this.isShown || e.isDefaultPrevented()) return this.isShown = true this.checkScrollbar() this.setScrollbar() this.$body.addClass('modal-open') this.escape() this.resize() this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this)) this.$dialog.on('mousedown.dismiss.bs.modal', function () { that.$element.one('mouseup.dismiss.bs.modal', function (e) { if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true }) }) this.backdrop(function () { var transition = $.support.transition && that.$element.hasClass('fade') if (!that.$element.parent().length) { that.$element.appendTo(that.$body) // don't move modals dom position } that.$element .show() .scrollTop(0) that.adjustDialog() if (transition) { that.$element[0].offsetWidth // force reflow } that.$element.addClass('in') that.enforceFocus() var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) transition ? that.$dialog // wait for modal to slide in .one('bsTransitionEnd', function () { that.$element.trigger('focus').trigger(e) }) .emulateTransitionEnd(Modal.TRANSITION_DURATION) : that.$element.trigger('focus').trigger(e) }) } Modal.prototype.hide = function (e) { if (e) e.preventDefault() e = $.Event('hide.bs.modal') this.$element.trigger(e) if (!this.isShown || e.isDefaultPrevented()) return this.isShown = false this.escape() this.resize() $(document).off('focusin.bs.modal') this.$element .removeClass('in') .off('click.dismiss.bs.modal') .off('mouseup.dismiss.bs.modal') this.$dialog.off('mousedown.dismiss.bs.modal') $.support.transition && this.$element.hasClass('fade') ? this.$element .one('bsTransitionEnd', $.proxy(this.hideModal, this)) .emulateTransitionEnd(Modal.TRANSITION_DURATION) : this.hideModal() } Modal.prototype.enforceFocus = function () { $(document) .off('focusin.bs.modal') // guard against infinite focus loop .on('focusin.bs.modal', $.proxy(function (e) { if (document !== e.target && this.$element[0] !== e.target && !this.$element.has(e.target).length) { this.$element.trigger('focus') } }, this)) } Modal.prototype.escape = function () { if (this.isShown && this.options.keyboard) { this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) { e.which == 27 && this.hide() }, this)) } else if (!this.isShown) { this.$element.off('keydown.dismiss.bs.modal') } } Modal.prototype.resize = function () { if (this.isShown) { $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this)) } else { $(window).off('resize.bs.modal') } } Modal.prototype.hideModal = function () { var that = this this.$element.hide() this.backdrop(function () { that.$body.removeClass('modal-open') that.resetAdjustments() that.resetScrollbar() that.$element.trigger('hidden.bs.modal') }) } Modal.prototype.removeBackdrop = function () { this.$backdrop && this.$backdrop.remove() this.$backdrop = null } Modal.prototype.backdrop = function (callback) { var that = this var animate = this.$element.hasClass('fade') ? 'fade' : '' if (this.isShown && this.options.backdrop) { var doAnimate = $.support.transition && animate this.$backdrop = $(document.createElement('div')) .addClass('modal-backdrop ' + animate) .appendTo(this.$body) this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) { if (this.ignoreBackdropClick) { this.ignoreBackdropClick = false return } if (e.target !== e.currentTarget) return this.options.backdrop == 'static' ? this.$element[0].focus() : this.hide() }, this)) if (doAnimate) this.$backdrop[0].offsetWidth // force reflow this.$backdrop.addClass('in') if (!callback) return doAnimate ? this.$backdrop .one('bsTransitionEnd', callback) .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : callback() } else if (!this.isShown && this.$backdrop) { this.$backdrop.removeClass('in') var callbackRemove = function () { that.removeBackdrop() callback && callback() } $.support.transition && this.$element.hasClass('fade') ? this.$backdrop .one('bsTransitionEnd', callbackRemove) .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : callbackRemove() } else if (callback) { callback() } } // these following methods are used to handle overflowing modals Modal.prototype.handleUpdate = function () { this.adjustDialog() } Modal.prototype.adjustDialog = function () { var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight this.$element.css({ paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '', paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : '' }) } Modal.prototype.resetAdjustments = function () { this.$element.css({ paddingLeft: '', paddingRight: '' }) } Modal.prototype.checkScrollbar = function () { var fullWindowWidth = window.innerWidth if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8 var documentElementRect = document.documentElement.getBoundingClientRect() fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left) } this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth this.scrollbarWidth = this.measureScrollbar() } Modal.prototype.setScrollbar = function () { var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10) this.originalBodyPad = document.body.style.paddingRight || '' var scrollbarWidth = this.scrollbarWidth if (this.bodyIsOverflowing) { this.$body.css('padding-right', bodyPad + scrollbarWidth) $(this.fixedContent).each(function (index, element) { var actualPadding = element.style.paddingRight var calculatedPadding = $(element).css('padding-right') $(element) .data('padding-right', actualPadding) .css('padding-right', parseFloat(calculatedPadding) + scrollbarWidth + 'px') }) } } Modal.prototype.resetScrollbar = function () { this.$body.css('padding-right', this.originalBodyPad) $(this.fixedContent).each(function (index, element) { var padding = $(element).data('padding-right') $(element).removeData('padding-right') element.style.paddingRight = padding ? padding : '' }) } Modal.prototype.measureScrollbar = function () { // thx walsh var scrollDiv = document.createElement('div') scrollDiv.className = 'modal-scrollbar-measure' this.$body.append(scrollDiv) var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth this.$body[0].removeChild(scrollDiv) return scrollbarWidth } // MODAL PLUGIN DEFINITION // ======================= function Plugin(option, _relatedTarget) { return this.each(function () { var $this = $(this) var data = $this.data('bs.modal') var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option) if (!data) $this.data('bs.modal', (data = new Modal(this, options))) if (typeof option == 'string') data[option](_relatedTarget) else if (options.show) data.show(_relatedTarget) }) } var old = $.fn.modal $.fn.modal = Plugin $.fn.modal.Constructor = Modal // MODAL NO CONFLICT // ================= $.fn.modal.noConflict = function () { $.fn.modal = old return this } // MODAL DATA-API // ============== $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) { var $this = $(this) var href = $this.attr('href') var target = $this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7 var $target = $(document).find(target) var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data()) if ($this.is('a')) e.preventDefault() $target.one('show.bs.modal', function (showEvent) { if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown $target.one('hidden.bs.modal', function () { $this.is(':visible') && $this.trigger('focus') }) }) Plugin.call($target, option, this) }) }(jQuery); /* ======================================================================== * Bootstrap: tooltip.js v3.4.1 * https://getbootstrap.com/docs/3.4/javascript/#tooltip * Inspired by the original jQuery.tipsy by Jason Frame * ======================================================================== * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; var DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn'] var uriAttrs = [ 'background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href' ] var ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i var DefaultWhitelist = { // Global attributes allowed on any supplied element below. '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN], a: ['target', 'href', 'title', 'rel'], area: [], b: [], br: [], col: [], code: [], div: [], em: [], hr: [], h1: [], h2: [], h3: [], h4: [], h5: [], h6: [], i: [], img: ['src', 'alt', 'title', 'width', 'height'], li: [], ol: [], p: [], pre: [], s: [], small: [], span: [], sub: [], sup: [], strong: [], u: [], ul: [] } /** * A pattern that recognizes a commonly useful subset of URLs that are safe. * * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts */ var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi /** * A pattern that matches safe data URLs. Only matches image, video and audio types. * * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts */ var DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i function allowedAttribute(attr, allowedAttributeList) { var attrName = attr.nodeName.toLowerCase() if ($.inArray(attrName, allowedAttributeList) !== -1) { if ($.inArray(attrName, uriAttrs) !== -1) { return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN)) } return true } var regExp = $(allowedAttributeList).filter(function (index, value) { return value instanceof RegExp }) // Check if a regular expression validates the attribute. for (var i = 0, l = regExp.length; i < l; i++) { if (attrName.match(regExp[i])) { return true } } return false } function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) { if (unsafeHtml.length === 0) { return unsafeHtml } if (sanitizeFn && typeof sanitizeFn === 'function') { return sanitizeFn(unsafeHtml) } // IE 8 and below don't support createHTMLDocument if (!document.implementation || !document.implementation.createHTMLDocument) { return unsafeHtml } var createdDocument = document.implementation.createHTMLDocument('sanitization') createdDocument.body.innerHTML = unsafeHtml var whitelistKeys = $.map(whiteList, function (el, i) { return i }) var elements = $(createdDocument.body).find('*') for (var i = 0, len = elements.length; i < len; i++) { var el = elements[i] var elName = el.nodeName.toLowerCase() if ($.inArray(elName, whitelistKeys) === -1) { el.parentNode.removeChild(el) continue } var attributeList = $.map(el.attributes, function (el) { return el }) var whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || []) for (var j = 0, len2 = attributeList.length; j < len2; j++) { if (!allowedAttribute(attributeList[j], whitelistedAttributes)) { el.removeAttribute(attributeList[j].nodeName) } } } return createdDocument.body.innerHTML } // TOOLTIP PUBLIC CLASS DEFINITION // =============================== var Tooltip = function (element, options) { this.type = null this.options = null this.enabled = null this.timeout = null this.hoverState = null this.$element = null this.inState = null this.init('tooltip', element, options) } Tooltip.VERSION = '3.4.1' Tooltip.TRANSITION_DURATION = 150 Tooltip.DEFAULTS = { animation: true, placement: 'top', selector: false, template: '', trigger: 'hover focus', title: '', delay: 0, html: false, container: false, viewport: { selector: 'body', padding: 0 }, sanitize : true, sanitizeFn : null, whiteList : DefaultWhitelist } Tooltip.prototype.init = function (type, element, options) { this.enabled = true this.type = type this.$element = $(element) this.options = this.getOptions(options) this.$viewport = this.options.viewport && $(document).find($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport)) this.inState = { click: false, hover: false, focus: false } if (this.$element[0] instanceof document.constructor && !this.options.selector) { throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!') } var triggers = this.options.trigger.split(' ') for (var i = triggers.length; i--;) { var trigger = triggers[i] if (trigger == 'click') { this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) } else if (trigger != 'manual') { var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) } } this.options.selector ? (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : this.fixTitle() } Tooltip.prototype.getDefaults = function () { return Tooltip.DEFAULTS } Tooltip.prototype.getOptions = function (options) { var dataAttributes = this.$element.data() for (var dataAttr in dataAttributes) { if (dataAttributes.hasOwnProperty(dataAttr) && $.inArray(dataAttr, DISALLOWED_ATTRIBUTES) !== -1) { delete dataAttributes[dataAttr] } } options = $.extend({}, this.getDefaults(), dataAttributes, options) if (options.delay && typeof options.delay == 'number') { options.delay = { show: options.delay, hide: options.delay } } if (options.sanitize) { options.template = sanitizeHtml(options.template, options.whiteList, options.sanitizeFn) } return options } Tooltip.prototype.getDelegateOptions = function () { var options = {} var defaults = this.getDefaults() this._options && $.each(this._options, function (key, value) { if (defaults[key] != value) options[key] = value }) return options } Tooltip.prototype.enter = function (obj) { var self = obj instanceof this.constructor ? obj : $(obj.currentTarget).data('bs.' + this.type) if (!self) { self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) $(obj.currentTarget).data('bs.' + this.type, self) } if (obj instanceof $.Event) { self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true } if (self.tip().hasClass('in') || self.hoverState == 'in') { self.hoverState = 'in' return } clearTimeout(self.timeout) self.hoverState = 'in' if (!self.options.delay || !self.options.delay.show) return self.show() self.timeout = setTimeout(function () { if (self.hoverState == 'in') self.show() }, self.options.delay.show) } Tooltip.prototype.isInStateTrue = function () { for (var key in this.inState) { if (this.inState[key]) return true } return false } Tooltip.prototype.leave = function (obj) { var self = obj instanceof this.constructor ? obj : $(obj.currentTarget).data('bs.' + this.type) if (!self) { self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) $(obj.currentTarget).data('bs.' + this.type, self) } if (obj instanceof $.Event) { self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false } if (self.isInStateTrue()) return clearTimeout(self.timeout) self.hoverState = 'out' if (!self.options.delay || !self.options.delay.hide) return self.hide() self.timeout = setTimeout(function () { if (self.hoverState == 'out') self.hide() }, self.options.delay.hide) } Tooltip.prototype.show = function () { var e = $.Event('show.bs.' + this.type) if (this.hasContent() && this.enabled) { this.$element.trigger(e) var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0]) if (e.isDefaultPrevented() || !inDom) return var that = this var $tip = this.tip() var tipId = this.getUID(this.type) this.setContent() $tip.attr('id', tipId) this.$element.attr('aria-describedby', tipId) if (this.options.animation) $tip.addClass('fade') var placement = typeof this.options.placement == 'function' ? this.options.placement.call(this, $tip[0], this.$element[0]) : this.options.placement var autoToken = /\s?auto?\s?/i var autoPlace = autoToken.test(placement) if (autoPlace) placement = placement.replace(autoToken, '') || 'top' $tip .detach() .css({ top: 0, left: 0, display: 'block' }) .addClass(placement) .data('bs.' + this.type, this) this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element) this.$element.trigger('inserted.bs.' + this.type) var pos = this.getPosition() var actualWidth = $tip[0].offsetWidth var actualHeight = $tip[0].offsetHeight if (autoPlace) { var orgPlacement = placement var viewportDim = this.getPosition(this.$viewport) placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' : placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' : placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' : placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' : placement $tip .removeClass(orgPlacement) .addClass(placement) } var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) this.applyPlacement(calculatedOffset, placement) var complete = function () { var prevHoverState = that.hoverState that.$element.trigger('shown.bs.' + that.type) that.hoverState = null if (prevHoverState == 'out') that.leave(that) } $.support.transition && this.$tip.hasClass('fade') ? $tip .one('bsTransitionEnd', complete) .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : complete() } } Tooltip.prototype.applyPlacement = function (offset, placement) { var $tip = this.tip() var width = $tip[0].offsetWidth var height = $tip[0].offsetHeight // manually read margins because getBoundingClientRect includes difference var marginTop = parseInt($tip.css('margin-top'), 10) var marginLeft = parseInt($tip.css('margin-left'), 10) // we must check for NaN for ie 8/9 if (isNaN(marginTop)) marginTop = 0 if (isNaN(marginLeft)) marginLeft = 0 offset.top += marginTop offset.left += marginLeft // $.fn.offset doesn't round pixel values // so we use setOffset directly with our own function B-0 $.offset.setOffset($tip[0], $.extend({ using: function (props) { $tip.css({ top: Math.round(props.top), left: Math.round(props.left) }) } }, offset), 0) $tip.addClass('in') // check to see if placing tip in new offset caused the tip to resize itself var actualWidth = $tip[0].offsetWidth var actualHeight = $tip[0].offsetHeight if (placement == 'top' && actualHeight != height) { offset.top = offset.top + height - actualHeight } var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) if (delta.left) offset.left += delta.left else offset.top += delta.top var isVertical = /top|bottom/.test(placement) var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight' $tip.offset(offset) this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical) } Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) { this.arrow() .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%') .css(isVertical ? 'top' : 'left', '') } Tooltip.prototype.setContent = function () { var $tip = this.tip() var title = this.getTitle() if (this.options.html) { if (this.options.sanitize) { title = sanitizeHtml(title, this.options.whiteList, this.options.sanitizeFn) } $tip.find('.tooltip-inner').html(title) } else { $tip.find('.tooltip-inner').text(title) } $tip.removeClass('fade in top bottom left right') } Tooltip.prototype.hide = function (callback) { var that = this var $tip = $(this.$tip) var e = $.Event('hide.bs.' + this.type) function complete() { if (that.hoverState != 'in') $tip.detach() if (that.$element) { // TODO: Check whether guarding this code with this `if` is really necessary. that.$element .removeAttr('aria-describedby') .trigger('hidden.bs.' + that.type) } callback && callback() } this.$element.trigger(e) if (e.isDefaultPrevented()) return $tip.removeClass('in') $.support.transition && $tip.hasClass('fade') ? $tip .one('bsTransitionEnd', complete) .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : complete() this.hoverState = null return this } Tooltip.prototype.fixTitle = function () { var $e = this.$element if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') { $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') } } Tooltip.prototype.hasContent = function () { return this.getTitle() } Tooltip.prototype.getPosition = function ($element) { $element = $element || this.$element var el = $element[0] var isBody = el.tagName == 'BODY' var elRect = el.getBoundingClientRect() if (elRect.width == null) { // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093 elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top }) } var isSvg = window.SVGElement && el instanceof window.SVGElement // Avoid using $.offset() on SVGs since it gives incorrect results in jQuery 3. // See https://github.com/twbs/bootstrap/issues/20280 var elOffset = isBody ? { top: 0, left: 0 } : (isSvg ? null : $element.offset()) var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() } var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null return $.extend({}, elRect, scroll, outerDims, elOffset) } Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } } Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { var delta = { top: 0, left: 0 } if (!this.$viewport) return delta var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 var viewportDimensions = this.getPosition(this.$viewport) if (/right|left/.test(placement)) { var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight if (topEdgeOffset < viewportDimensions.top) { // top overflow delta.top = viewportDimensions.top - topEdgeOffset } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset } } else { var leftEdgeOffset = pos.left - viewportPadding var rightEdgeOffset = pos.left + viewportPadding + actualWidth if (leftEdgeOffset < viewportDimensions.left) { // left overflow delta.left = viewportDimensions.left - leftEdgeOffset } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset } } return delta } Tooltip.prototype.getTitle = function () { var title var $e = this.$element var o = this.options title = $e.attr('data-original-title') || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) return title } Tooltip.prototype.getUID = function (prefix) { do prefix += ~~(Math.random() * 1000000) while (document.getElementById(prefix)) return prefix } Tooltip.prototype.tip = function () { if (!this.$tip) { this.$tip = $(this.options.template) if (this.$tip.length != 1) { throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!') } } return this.$tip } Tooltip.prototype.arrow = function () { return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')) } Tooltip.prototype.enable = function () { this.enabled = true } Tooltip.prototype.disable = function () { this.enabled = false } Tooltip.prototype.toggleEnabled = function () { this.enabled = !this.enabled } Tooltip.prototype.toggle = function (e) { var self = this if (e) { self = $(e.currentTarget).data('bs.' + this.type) if (!self) { self = new this.constructor(e.currentTarget, this.getDelegateOptions()) $(e.currentTarget).data('bs.' + this.type, self) } } if (e) { self.inState.click = !self.inState.click if (self.isInStateTrue()) self.enter(self) else self.leave(self) } else { self.tip().hasClass('in') ? self.leave(self) : self.enter(self) } } Tooltip.prototype.destroy = function () { var that = this clearTimeout(this.timeout) this.hide(function () { that.$element.off('.' + that.type).removeData('bs.' + that.type) if (that.$tip) { that.$tip.detach() } that.$tip = null that.$arrow = null that.$viewport = null that.$element = null }) } Tooltip.prototype.sanitizeHtml = function (unsafeHtml) { return sanitizeHtml(unsafeHtml, this.options.whiteList, this.options.sanitizeFn) } // TOOLTIP PLUGIN DEFINITION // ========================= function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.tooltip') var options = typeof option == 'object' && option if (!data && /destroy|hide/.test(option)) return if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) if (typeof option == 'string') data[option]() }) } var old = $.fn.tooltip $.fn.tooltip = Plugin $.fn.tooltip.Constructor = Tooltip // TOOLTIP NO CONFLICT // =================== $.fn.tooltip.noConflict = function () { $.fn.tooltip = old return this } }(jQuery); /* ======================================================================== * Bootstrap: popover.js v3.4.1 * https://getbootstrap.com/docs/3.4/javascript/#popovers * ======================================================================== * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // POPOVER PUBLIC CLASS DEFINITION // =============================== var Popover = function (element, options) { this.init('popover', element, options) } if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js') Popover.VERSION = '3.4.1' Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, { placement: 'right', trigger: 'click', content: '', template: '' }) // NOTE: POPOVER EXTENDS tooltip.js // ================================ Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype) Popover.prototype.constructor = Popover Popover.prototype.getDefaults = function () { return Popover.DEFAULTS } Popover.prototype.setContent = function () { var $tip = this.tip() var title = this.getTitle() var content = this.getContent() if (this.options.html) { var typeContent = typeof content if (this.options.sanitize) { title = this.sanitizeHtml(title) if (typeContent === 'string') { content = this.sanitizeHtml(content) } } $tip.find('.popover-title').html(title) $tip.find('.popover-content').children().detach().end()[ typeContent === 'string' ? 'html' : 'append' ](content) } else { $tip.find('.popover-title').text(title) $tip.find('.popover-content').children().detach().end().text(content) } $tip.removeClass('fade top bottom left right in') // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do // this manually by checking the contents. if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide() } Popover.prototype.hasContent = function () { return this.getTitle() || this.getContent() } Popover.prototype.getContent = function () { var $e = this.$element var o = this.options return $e.attr('data-content') || (typeof o.content == 'function' ? o.content.call($e[0]) : o.content) } Popover.prototype.arrow = function () { return (this.$arrow = this.$arrow || this.tip().find('.arrow')) } // POPOVER PLUGIN DEFINITION // ========================= function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.popover') var options = typeof option == 'object' && option if (!data && /destroy|hide/.test(option)) return if (!data) $this.data('bs.popover', (data = new Popover(this, options))) if (typeof option == 'string') data[option]() }) } var old = $.fn.popover $.fn.popover = Plugin $.fn.popover.Constructor = Popover // POPOVER NO CONFLICT // =================== $.fn.popover.noConflict = function () { $.fn.popover = old return this } }(jQuery); /* ======================================================================== * Bootstrap: scrollspy.js v3.4.1 * https://getbootstrap.com/docs/3.4/javascript/#scrollspy * ======================================================================== * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // SCROLLSPY CLASS DEFINITION // ========================== function ScrollSpy(element, options) { this.$body = $(document.body) this.$scrollElement = $(element).is(document.body) ? $(window) : $(element) this.options = $.extend({}, ScrollSpy.DEFAULTS, options) this.selector = (this.options.target || '') + ' .nav li > a' this.offsets = [] this.targets = [] this.activeTarget = null this.scrollHeight = 0 this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this)) this.refresh() this.process() } ScrollSpy.VERSION = '3.4.1' ScrollSpy.DEFAULTS = { offset: 10 } ScrollSpy.prototype.getScrollHeight = function () { return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight) } ScrollSpy.prototype.refresh = function () { var that = this var offsetMethod = 'offset' var offsetBase = 0 this.offsets = [] this.targets = [] this.scrollHeight = this.getScrollHeight() if (!$.isWindow(this.$scrollElement[0])) { offsetMethod = 'position' offsetBase = this.$scrollElement.scrollTop() } this.$body .find(this.selector) .map(function () { var $el = $(this) var href = $el.data('target') || $el.attr('href') var $href = /^#./.test(href) && $(href) return ($href && $href.length && $href.is(':visible') && [[$href[offsetMethod]().top + offsetBase, href]]) || null }) .sort(function (a, b) { return a[0] - b[0] }) .each(function () { that.offsets.push(this[0]) that.targets.push(this[1]) }) } ScrollSpy.prototype.process = function () { var scrollTop = this.$scrollElement.scrollTop() + this.options.offset var scrollHeight = this.getScrollHeight() var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height() var offsets = this.offsets var targets = this.targets var activeTarget = this.activeTarget var i if (this.scrollHeight != scrollHeight) { this.refresh() } if (scrollTop >= maxScroll) { return activeTarget != (i = targets[targets.length - 1]) && this.activate(i) } if (activeTarget && scrollTop < offsets[0]) { this.activeTarget = null return this.clear() } for (i = offsets.length; i--;) { activeTarget != targets[i] && scrollTop >= offsets[i] && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1]) && this.activate(targets[i]) } } ScrollSpy.prototype.activate = function (target) { this.activeTarget = target this.clear() var selector = this.selector + '[data-target="' + target + '"],' + this.selector + '[href="' + target + '"]' var active = $(selector) .parents('li') .addClass('active') if (active.parent('.dropdown-menu').length) { active = active .closest('li.dropdown') .addClass('active') } active.trigger('activate.bs.scrollspy') } ScrollSpy.prototype.clear = function () { $(this.selector) .parentsUntil(this.options.target, '.active') .removeClass('active') } // SCROLLSPY PLUGIN DEFINITION // =========================== function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.scrollspy') var options = typeof option == 'object' && option if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options))) if (typeof option == 'string') data[option]() }) } var old = $.fn.scrollspy $.fn.scrollspy = Plugin $.fn.scrollspy.Constructor = ScrollSpy // SCROLLSPY NO CONFLICT // ===================== $.fn.scrollspy.noConflict = function () { $.fn.scrollspy = old return this } // SCROLLSPY DATA-API // ================== $(window).on('load.bs.scrollspy.data-api', function () { $('[data-spy="scroll"]').each(function () { var $spy = $(this) Plugin.call($spy, $spy.data()) }) }) }(jQuery); /* ======================================================================== * Bootstrap: tab.js v3.4.1 * https://getbootstrap.com/docs/3.4/javascript/#tabs * ======================================================================== * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // TAB CLASS DEFINITION // ==================== var Tab = function (element) { // jscs:disable requireDollarBeforejQueryAssignment this.element = $(element) // jscs:enable requireDollarBeforejQueryAssignment } Tab.VERSION = '3.4.1' Tab.TRANSITION_DURATION = 150 Tab.prototype.show = function () { var $this = this.element var $ul = $this.closest('ul:not(.dropdown-menu)') var selector = $this.data('target') if (!selector) { selector = $this.attr('href') selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 } if ($this.parent('li').hasClass('active')) return var $previous = $ul.find('.active:last a') var hideEvent = $.Event('hide.bs.tab', { relatedTarget: $this[0] }) var showEvent = $.Event('show.bs.tab', { relatedTarget: $previous[0] }) $previous.trigger(hideEvent) $this.trigger(showEvent) if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return var $target = $(document).find(selector) this.activate($this.closest('li'), $ul) this.activate($target, $target.parent(), function () { $previous.trigger({ type: 'hidden.bs.tab', relatedTarget: $this[0] }) $this.trigger({ type: 'shown.bs.tab', relatedTarget: $previous[0] }) }) } Tab.prototype.activate = function (element, container, callback) { var $active = container.find('> .active') var transition = callback && $.support.transition && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length) function next() { $active .removeClass('active') .find('> .dropdown-menu > .active') .removeClass('active') .end() .find('[data-toggle="tab"]') .attr('aria-expanded', false) element .addClass('active') .find('[data-toggle="tab"]') .attr('aria-expanded', true) if (transition) { element[0].offsetWidth // reflow for transition element.addClass('in') } else { element.removeClass('fade') } if (element.parent('.dropdown-menu').length) { element .closest('li.dropdown') .addClass('active') .end() .find('[data-toggle="tab"]') .attr('aria-expanded', true) } callback && callback() } $active.length && transition ? $active .one('bsTransitionEnd', next) .emulateTransitionEnd(Tab.TRANSITION_DURATION) : next() $active.removeClass('in') } // TAB PLUGIN DEFINITION // ===================== function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.tab') if (!data) $this.data('bs.tab', (data = new Tab(this))) if (typeof option == 'string') data[option]() }) } var old = $.fn.tab $.fn.tab = Plugin $.fn.tab.Constructor = Tab // TAB NO CONFLICT // =============== $.fn.tab.noConflict = function () { $.fn.tab = old return this } // TAB DATA-API // ============ var clickHandler = function (e) { e.preventDefault() Plugin.call($(this), 'show') } $(document) .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler) .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler) }(jQuery); /* ======================================================================== * Bootstrap: affix.js v3.4.1 * https://getbootstrap.com/docs/3.4/javascript/#affix * ======================================================================== * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ +function ($) { 'use strict'; // AFFIX CLASS DEFINITION // ====================== var Affix = function (element, options) { this.options = $.extend({}, Affix.DEFAULTS, options) var target = this.options.target === Affix.DEFAULTS.target ? $(this.options.target) : $(document).find(this.options.target) this.$target = target .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this)) .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this)) this.$element = $(element) this.affixed = null this.unpin = null this.pinnedOffset = null this.checkPosition() } Affix.VERSION = '3.4.1' Affix.RESET = 'affix affix-top affix-bottom' Affix.DEFAULTS = { offset: 0, target: window } Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) { var scrollTop = this.$target.scrollTop() var position = this.$element.offset() var targetHeight = this.$target.height() if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false if (this.affixed == 'bottom') { if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom' return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom' } var initializing = this.affixed == null var colliderTop = initializing ? scrollTop : position.top var colliderHeight = initializing ? targetHeight : height if (offsetTop != null && scrollTop <= offsetTop) return 'top' if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom' return false } Affix.prototype.getPinnedOffset = function () { if (this.pinnedOffset) return this.pinnedOffset this.$element.removeClass(Affix.RESET).addClass('affix') var scrollTop = this.$target.scrollTop() var position = this.$element.offset() return (this.pinnedOffset = position.top - scrollTop) } Affix.prototype.checkPositionWithEventLoop = function () { setTimeout($.proxy(this.checkPosition, this), 1) } Affix.prototype.checkPosition = function () { if (!this.$element.is(':visible')) return var height = this.$element.height() var offset = this.options.offset var offsetTop = offset.top var offsetBottom = offset.bottom var scrollHeight = Math.max($(document).height(), $(document.body).height()) if (typeof offset != 'object') offsetBottom = offsetTop = offset if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element) if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element) var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom) if (this.affixed != affix) { if (this.unpin != null) this.$element.css('top', '') var affixType = 'affix' + (affix ? '-' + affix : '') var e = $.Event(affixType + '.bs.affix') this.$element.trigger(e) if (e.isDefaultPrevented()) return this.affixed = affix this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null this.$element .removeClass(Affix.RESET) .addClass(affixType) .trigger(affixType.replace('affix', 'affixed') + '.bs.affix') } if (affix == 'bottom') { this.$element.offset({ top: scrollHeight - height - offsetBottom }) } } // AFFIX PLUGIN DEFINITION // ======================= function Plugin(option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.affix') var options = typeof option == 'object' && option if (!data) $this.data('bs.affix', (data = new Affix(this, options))) if (typeof option == 'string') data[option]() }) } var old = $.fn.affix $.fn.affix = Plugin $.fn.affix.Constructor = Affix // AFFIX NO CONFLICT // ================= $.fn.affix.noConflict = function () { $.fn.affix = old return this } // AFFIX DATA-API // ============== $(window).on('load', function () { $('[data-spy="affix"]').each(function () { var $spy = $(this) var data = $spy.data() data.offset = data.offset || {} if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom if (data.offsetTop != null) data.offset.top = data.offsetTop Plugin.call($spy, data) }) }) }(jQuery); ================================================ FILE: doc/manual/alt_layouts.md ================================================ --- title: Alt Layouts layout: page author: Jay Shafstall --- Alt Layouts are for when you want to create more than one physical .html file per .md file. This is most useful when the additional .html files do not depend on the content of the original page, but on the front matter attributes. # Usage To enable alt layouts for a .md file, add an `alt_layouts` attribute to the front matter of a page. This is a list of objects containing two attributes, `layout` and `location`. The `layout` attribute gives the name of an alternate layout to use. The `location` attribute gives the directory where the .html file should be put. That directory must already exist in your directory structure. Also add either `items_index` or `items_filter` to say where the list of it # Example The following is a sample of generating two additional .html files for a product page: ``` layout: product alt_layouts: - layout: confirmation location: confirmations - layout: product_details location: details ``` If the original foo.md file was in the products directory, three .html files would be generated: ``` products/foo.html confirmations/foo.html details/foo.html ``` ================================================ FILE: doc/manual/authoring.md ================================================ --- title: Authoring layout: page pager: true author: Jan Decaluwe --- Content ======= In Urubu, content is entered in [markdown] format. This is a lightweight format that feels like a natural way to write content in plain text. Stock markdown has a small feature set. For example, it does not even support tables. For this reason, Urubu supports some extensions. In particular, it supports the [markdown_extra] extensions that have become an industry standard, as well as a few others. The most notable supported extensions are: * [tables] * [attr_list] * [abbrev] * [def_list] * [fenced_code] * [code_hilite] Code ==== Urubu intents to offer good support for software projects. Therefore, it supports nicely rendered code blocks. One part of the solution is [fenced_code], provided by the Markdown Extra extensions. This lets you enter language-specific code blocks without the need for indentation. The second part is the [code_hilite] extension of Python-Markdown. This extension enables language-specific syntax highlighting through the [pygments] library. To properly render the highlighted code, you will need to add a `syntax.css` stylesheet. A good solution is to use the [syntax stylesheet from GitHub][syntax_github]. [syntax_github]: https://github.com/mojombo/tpw/blob/master/css/syntax.css Reference links =============== Stock Markdown supports "reference links" that are resolved by defining them later in the file. For example, you can use `[urubu]` in your content and further on define it as follows: ``` [urubu]: http://urubu.jandecaluwe.com ``` This is nice for readability, but it all remains file based. Urubu extends this behavior by automatically resolving [structure#Project-wide reference ids]. This feature is implemented as a Markdown extension. Note that it doesn't require a syntax change. It enables page linking like in wikis. In addition, you can add a fragment, like `#some-anchor`, to the reference id. This represents a link to an anchor within a page. Since Urubu automatically adds slugified anchors to markdown headers, you can use those as targets. For instance, `[authoring#reference-links]` is a link to the current [authoring#Reference links] section. You can also define your own anchors using [attr_list]. Markdown supports reference links without a text. In that case, Urubu inserts an appropriate text in the html. For a reference link with no fragment, the title of the page is inserted. For a reference link with a fragment, the fragment text is inserted. To make the result more readable, you can use non-slugified fragment text. For example, `[authoring#Reference links]` also links to the present section, and is rendered as [authoring#Reference links]. ================================================ FILE: doc/manual/building.md ================================================ --- title: Project building layout: page pager: true author: Jan Decaluwe --- The `urubu` command =================== After installation, an `urubu` command will be available. If you prefer, you can call the installed package as a script using `python -m urubu`, with the same effect. Subcommands =========== The `urubu` command supports two subcommands. Run these commands from the top level project directory. `urubu build` : Build the website. The website will be in the `_build` subdirectory. `urubu serve` : Start a local webserver to serve the website as you develop it. The website will be available at `localhost:8000`. Run this command in a separate terminal window, and kill the server when you are done. Development flow ================ I prefer to put the commands in a Makefile, so that I can run `make` to build and `make serve` to start a server. Currently, you have to build the site explicitly to see the development changes in the browser. ================================================ FILE: doc/manual/extensions.md ================================================ --- title: Markdown extensions layout: page pager: true author: Jan Decaluwe --- Introduction ============ Urubu implements a number of Markdown extensions. These extensions do not change or extend the Markdown syntax. Rather, they add interesting features by processing and rendering the Markdown source in more sophisticated ways. The extensions are described in more detail below. Project-wide reference ids ========================== Urubu implements a Markdown extension to resolve project-wide reference ids. This means that all pages in the project are automatically available as reference ids, and can be referred to using Markdown's syntax for reference links. This feature is described in more detail in the sections [/manual/structure#Project-wide reference ids] and [/manual/authoring#Reference links]. It is Urubu's most important extension and a fundamental feature of the tool. Bootstrap-specific extensions ============================= Urubu is designed to play well with [bootstrap]. To use certain Bootstrap features, it has extensions that add Bootstrap classes to certain tags. More specifically, the following classes are added: table : Added to the `
` tag. This defines basic styling for tables. dl-horizontal : Added to the `
` tag that defines definition lists. This creates a horizontal layout for definition lists in wide viewports. Support for the `mark` tag ========================== The html5 specification added _a new tag to highlight text_: the `` tag. For a good explanation of its purpose and the differences with the `` and `` tags, see [this answer on Stack Overflow][mark]. [mark]: http://stackoverflow.com/a/14741437 Urubu supports lightweight markup for this tag by taking advantage of a redundancy in Markdown. In standard Markdown, you can either use asterisks (`*`) or underscores (`_`) to indicate emphasis. With the Urubu extension, the underscore (`_`) version is rendered using `` instead. This is an experimental feature that may be taken out if there are serious objections, although at this point there do not seem to be disadvantages. To disable the feature, the `mark_tag_support` variable can be set to `false` in the `_site.yml` file. ================================================ FILE: doc/manual/hooks.md ================================================ --- title: Python hooks layout: page pager: true author: Jan Decaluwe --- Introduction ============= Urubu supports Python hooks to make templating easier. Upon a build, it tries to import a `_python` module or package, and looks for hook variables with predefined names. The following hooks are defined: Variable | Description ----------------------|------------- `filters` | A mapping from filter names to filter functions. `process_info` | A function to inspect and process content file info. You have to make sure that these names are exported correctly. For example, if you organize `_python` as a package, it could look as follows: ``` _python/ __init__.py filters.py hooks.py ``` If `filters` is defined in `filters.py`, and `process_info` in `hooks.py`, the `__init__.py` file would contain: ``` from .filters import filters from .hooks import process_info ``` The `filters` hook ================== Filters functions should be defined as [custom filters in Jinja2][jinja2_filters]. [jinja2_filters]: http://jinja.pocoo.org/docs/api/#custom-filters As a typical example, consider a filter that converts a date value into a desired format. The `filters.py` module would contain the following: ``` def dateformat(value, format="%d-%b-%Y"): return value.strftime(format) filters = {} filters['dateformat'] = dateformat ``` You can then use the `dateformat` filter in templates. The `process_info` hook ======================= The interface of the `process_info` function is as follows: ``` def process(info, site): ... ``` This function is called for every content file in the project. The `site` variable provides access to the site variables defined in `_site.yml`. The `info` variable contains the file content info as it is being constructed by Urubu. At the moment of the call, the following inferred attributes are available: Attribute | Description ---------------|--------------------------- `id` | The unique id by which the object is known in the project. `url` | The url of the object. `components` | The components of the object's pathname, without file extension, as a list. `fn` | The pathname of the file or directory corresponding the object. `mdate` | Modification date In addition, all attributes specified in the YAML front matter of the corresponding content file are available as attributes of the `info` object. The `site` and `info` variables are Python dictionaries. This means that the attributes are available via key access, not via Python attribute access. This is because the YAML reader constructs Python dictionaries from the front matter. The `process_info` function can can inspect the attributes, verify and modify them, and add additional ones. `process_info` examples ======================= Defining a default `layout` --------------------------- It can be handy to define a default `layout` for the case this mandatory attribute is not specified in the content file. Suppose we want a default `index` layout for index files, and a `page` layout for other files: ``` def process_info(info, site): if 'layout' not in info: if info['components'][-1] == 'index': info['layout'] = 'index' else: info['layout'] = 'page' ``` Defining a specific layout -------------------------- Suppose we have a `blog` directory and we want to automatically define a specific `post` layout for blog posts: ``` def process_info(info, site): components = info['components'] if len(components) == 2: if components[0] == 'blog' and components[1] != 'index': process_post(info) def process_post(info): if not 'layout' in info: info['layout'] = 'post' ``` ================================================ FILE: doc/manual/index.md ================================================ --- title: Manual layout: index content: - intro - install - structure - authoring - building - templates - templating-in-pages - hooks - extensions - search - pagination - alt_layouts --- ================================================ FILE: doc/manual/install.md ================================================ --- title: Installation layout: page pager: true date: 2014-01-10 --- Urubu works with modern versions of Python 2 and Python 3 using the same codebase. More specifically, it requires Python 2.7 or Python 3.4. You can install Urubu using pip: ``` pip install urubu ``` To upgrade an existing installation to the latest version, use: ``` pip install --upgrade urubu ``` If pip is not yet available on your system, follow the [pip installation instructions][pip_install]. [pip_install]: http://www.pip-installer.org/en/latest/installing.html You may want to install Urubu in an isolated environment using [virtualenv]. Urubu depends on a number of libraries that will automatically be installed if not yet available: [python_markdown], [pyyaml], [pygments] and [jinja2]. For a quick way to set up a new Urubu project, visit [urubu-quickstart]. ================================================ FILE: doc/manual/intro.md ================================================ --- title: Concepts layout: page pager: true author: Jan Decaluwe --- Introduction ============ Welcome to Urubu! My name is Jan Decaluwe and I am Urubu's author. Urubu is a micro CMS for static websites. The qualification "micro* means that it has a small feature set, defined by what I need for my purposes. To know whether it is the right tool for you, check out [/start]. *[CMS]: Content Management System Urubu's design philosophy is radical reuse of great software and ideas from others. In the following sections, I will describe its concepts and how they are implemented. Authoring ========= In Urubu, content is entered in [markdown] format. This is a lightweight format that feels like a natural way to write content in plain text. Markdown support in Urubu is implemented by the [python_markdown] package, that converts the format to html. Urubu also supports the industry standard [markdown_extra] extensions, with useful features such as tables and definition lists. Urubu supports nicely rendered code blocks, an essential feature for software projects documentation. [fenced_code] are provided by the Markdown Extra extensions. This lets you enter language-specific code blocks without the need for indentation. The [code_hilite] extension of Python-Markdown enables language-specific syntax highlighting via the [pygments] library. Configuration ============= The configuration options in Urubu are kept minimal, in the spirit of "There should be one obvious way to do it". Where used, the configuration format is YAML, implemented by the [pyyaml] library. Configuration is mostly distributed, in the sense that every content file should have a *front matter*, that specifies the title, layout, date and so on. This idea is found in many tools, but Urubu reuses the technique from [jekyll]. YAML front matter is specified between two sets of triple dashes. Urubu extends this configuration technique by treating index files specially. Each folder in the site should have an index file (called `index.md`) that specifies the ordered folder content. This can be done explicitly by listing the files, or implicitly by specifying how the files should be ordered. Templating ========== With templates you specify the html layout for a particular type of a page. In a template you can mix plain html with control structures and variable interpolation. The actual html page is generated by evaluating the template with the appropriate evaluation context provided by Urubu. Urubu uses the [jinja2] templating language library. Theming ======= A theme refers to the general look and feel of a web site. Partially this is defined by the templates as discussed above. The other part is defined in style sheets, with a technique known as Cascading Style Sheets (CSS). Basically this is a sophisticated technique to define how the various html elements should be rendered by the web browser. With Urubu, you are free to design and use your own style sheets. However, it has been developed with [bootstrap] in mind. Bootstrap is a professionally-designed framework with lots of useful predefined styles components. Urubu generates html that is Bootstrap-friendly, and infers the appropriate template variables for certain Bootstrap components. A great feature of Bootstrap is that it is "mobile first". This means that your website will automatically adapt to any platform - smartphone, tablet or widescreen. A notable project is [bootswatch]. This is a set of themes designed as drop-in replacement for the stock bootstrap styles. This gives you an effortless option to change the look and feel of your website. Navigation ========== I am a big fan of Steve Krug's book [Don't make me think][dmmt], and I feel that the lessons from this book are still often ignored. Actually, the lack of focus of other tools on these ideas are the main reason why I wrote Urubu. [dmmt]: http://www.amazon.com/Dont-Make-Me-Think-Usability/dp/0321344758 A main concept is good navigation. Urubu supports various techniques by inferring navigation-oriented variables and making them available to the template engine. Moreover, they work well with some well-defined and nicely style [bootstrap] navigation components. In this way, you can easily implement the following: * a navbar for navigation between major sections * table of contents of a page in a sidebar * breadcrumbs * previous and next pager buttons * active page or section highlighting Other techniques, independent from Urubu, can also help. Note for example that the sidebar on this page is "affixed": it moves as you scroll through the page, but never leaves the viewport. (Note: this description assumes that the viewport is wide enough to accomodate the sidebar.) At any time, the full structure of the page remains visible and available for navigation. This was implemented by borrowing code from the [bootstrap] theme. Project-wide reference ids ========================== Markdown defines the concept of a reference link. This is a way to refer to a page or an url using a reference id. The syntax of a reference link is a reference id between square brackets, for example `[intro]`. Urubu supports the concept of project-wide reference ids. First, global reference ids can be defined in the site configuration file. Moreover, all content pages and folders have a corresponding reference id: their pathname without extension. In this case, reference links are similar to wiki links, the typical way to link between pages in wiki's. Standard Markdown only resolves reference ids that are defined within the file. Urubu extends this behavior by resolving them over the project. This feature is implemented as a Markdown extension. Note that it doesn't require new syntax. Project-wide reference ids are a unique Urubu feature. One of the messages of Steve Krug's book is that the text that you click should be the title of the page where you land. Therefore, when you use reference links, Urubu will insert the page title in the generated html (unless you specify an alternative text explicitly). Development and deployment ========================== You can develop a Urubu project is like a software project, from a git or mercurial repository. This gives you best-in-class revision control. Moreover, all the workflows that these systems provide are available. For example, you can develop your website collaboratively on [github] or [bitbucket]. Finally, it is easy to automate deployment, triggered by a push of the generated site to an upstream repository. ================================================ FILE: doc/manual/pagination.md ================================================ --- title: Pagination layout: page author: Jay Shafstall --- There are times when an index file will contain more entries than you want to include in a single page. Pagination allows Urubu to automatically split that page into separate pages in your site. # Usage To enable pagination, add an `items_per_page` attribute to the front matter of an index page. Also add either `items_index` or `items_filter` to say where the list of items should pull from. To pull from files in the current directory, with 5 items per page: ``` items_per_page: 5 items_index: this ``` To pull from a different index contents: ``` items_per_page: 5 items_index: news\index.md ``` To filter the contents: ``` items_per_page: 5 items_filter: mysteries time-loop ``` # New Page Variables Each of the pages generated by pagination will have three new variables available to layouts. `numpages` - the number of total pages generated `prevpage` - the previous page in the chain `nextpage` - the next page in the chain ## Example pagination controls The following is a sample of generating pagination controls in a layout: ``` {% if this.numpages %}
    {% if this.prevpage %}
  • <
  • {% endif %} {% for page in this.pages %} {% if page.pagenum == this.thispage %}
  • {{page.pagenum}}
  • {% else %}
  • {{page.pagenum}}
  • {% endif %} {% endfor %} {% if this.nextpage %}
  • >
  • {% endif %}
{% endif %} ``` ================================================ FILE: doc/manual/search.md ================================================ --- title: Adding Search layout: page pager: true author: Jan Decaluwe --- Introduction ============ A static site cannot natively support dynamic services. Fortunately, it is often an elegant solution to integrate third party solutions within a static site. One of the most prominent examples is Search. One possibility is integrating an external service such as Google Custom Search. The disadvantage is that one has either to pay for it or accept the branding. As an alternative, Urubu supports Tipue Search, an open source solution based on javascript executed in the browser. As part of the site building, Urubu generates a view on the searchable content. In this chapter, we describe how the integration is accomplished. Installing Tipue Search ======================= The first step is to [download][1] the Tipue Search distribution. It contains a `tipuesearch` directory. Copy that directory to the top level of your project. As usual, Urubu copies it to the built website, so that the required stylesheets and javascript files are available in the expected location. Do not rename the `tipuesearch` directory. The existence of that directory triggers Urubu's support. The search box ============== The next step is to create a search box. Suppose you want to make it part of the navbar, as in the present site. This is achieved with the following html code: ```
``` The `name` and the `id` values in the `` tag of the search box are mandatory for Tipue Search. The typical place for this code would be in the navbar code in a basic layout for the site. The search results page ======================= The next step is to create a search result page. To integrate it we first create a dedicated layout using template inheritance. Let us assume that is there is a `head_addon` and a `body_addon` block to add links and scripts to the `` section respectively. The `search.html` layout is then as follows: ``` {% raw %} {% extends "page.html" %} {% block head_addon %} {% endblock %} {% block body_addon %} {% endblock %} {% endraw %} ``` We inherit from a `page.html` layout. In the `head_addon` block, we add the Tipue Search style sheet for the result page. In the `body_addon` page we add the Tipue Search java script modules, and the inline script that generates the results. This setup assumes that the jQuery javascript library itself is already loaded in the body of the parent layout, with a line like the following: ``` ``` If you use the Bootstrap javascript modules, that will be the case. In the top level project directory, we can then create a `search.md` files that uses the `search.html` layout and has the generated search results as its content: ``` --- title: Search results layout: search ---
``` After building the site, there will be a functional `search.html` file in the top-level directory. **Note** The `tipuesearch.css` stylesheet also contains styling for the search box. The result may be undesirable if you use your own styling, like in the present website. The workaround is to comment the search box styling out. {.text-info} The search content ================== The searchable content itself is a JSON object defined in the file `tipuesearch/tipuesearch_content.json`. This is where Urubu kicks in: this file is generated automatically. Extracting meaningful searchable content from a web site is not trivial. A design decision for Urubu was to use modern techniques to help with this. In particular, Urubu will only consider content that is wrapped with the `
` tag. This is a relatively new html5 tag with exactly the purpose to indicate the page content explicitly. The site designer should therefore review the site layouts and wrap all searchable content with the `
` tag. Typically, this is the region were the `this.body` variable is called in a template. **Note** The `
` tag is not supported in IE11. A popular workaround is to use the `html5shiv.js` Javascript module. Layouts based on Bootstrap do this already. {.text-info} [1]: https://github.com/calfzhou/Tipue-Search ================================================ FILE: doc/manual/structure.md ================================================ --- title: Project structure layout: page pager: true author: Jan Decaluwe --- The project directory ===================== A typical Urubu project directory looks as follows: ``` Makefile _site.yml _layouts/_base.html page.html ... _python/__init__.py validators.py filters.py css/... js/... index.md folder1/index.md file1.md pic1.png ... folder2/index.md file2.md file3.md ... ``` Files and directories with pathnames starting with an underscore `_` are special. They are used during processing, but excluded from the built website. Their function will be discussed below. The `css` and `js` directories are just an example of how CSS style sheets and javascript files could be organized. You can use any organization that you prefer. Content files are in Markdown format and should have the `.md` extension. You have complete freedom in organizing them in directories. However, every directory should have an `index.md` file, including the top-level directory. Processing rules ================ Urubu generates a website by processing the files and directory in the project directory, and putting the result in a `_build` subdirectory. The processing depends on the pathname as follows: * a `Makefile` is ignored and not copied to the build. * files and directories starting with a dot `.` or underscore `_` are ignored and not copied to the build. * Markdown files with extension `.md` are converted to a html file that is put into the build in the same relative location. * all other files and directories are copied unmodified to the build in the same relative location. As a result of the project organization and the build process, the structure of the build matches the structure of the project directory. The relative location of all files is thus preserved. Special files and directories ============================= `_site.yml` ----------- This file contains site configuration info in YAML format. Currently, these are the predefined attributes: Attribute | Description --------------------|------------- `reflinks` | Holds a mapping from reference ids to link objects. `baseurl` | Prefix for generated local URLs `file_ext` | Change default file extension (`'.html'`) for processed `.md` files `link_ext` | Change default file extension (`'.html'`) for links to site's pages `ignore_patterns` | List of additional file names or globs to be ignored during processing `keep_files` | List of explicit file names be kept, overriding any ignores `strict_undefined` | Set the default behavior regarding undefined template variables Link objects, for the `reflinks` attribute, are a mapping with an `url` key that maps to the link URL and a `title` key that maps to the link title. The `baseurl` option mirrors the same feature in [Jekyll][jekyll-options]. It allows you to specify a prefix for all local URLs generated within your site. This is necessary when your site will be served from a URL that has more than just the hostname. For example, on GitHub Pages sites are served from http://username.github.io/project_name/, so Urubu needs to include that `/project_name/` in generated URLs pointing to local content. `baseurl` should be specified with no beginning or trailing slashes, e.g.: ```yaml baseurl: prefix ``` [jekyll-options]: http://jekyllrb.com/docs/configuration/#serve-command-options The file extension attributes, `file_ext` and `link_ext`, are both usually set to the same value (i.e. `'.php'`), unless the target site has .htaccess rewrite rules that affect the file extensions. Examples of this are sites that internally redirect pages like `www.test.com/account` to `www.test.com/account.htm`. For this case, one would need to set `file_ext` to `'.htm'`, so Urubu generated files have the `.htm` extension, whereas `link_ext` would be set to `''`, so that the `a href` links are directed to the files without extension. Otherwise, `file_ext` and `link_ext` should be set to the same extension, specially during testing, so that the simple web server invoked by `urubu serve` works fine, as well as any web server that does not rewrite the file extensions of the requests. The `ignore_patterns` attribute specifies glob-style patterns to be ignored during processing, in addition to the default ones according to the [#Processing Rules]. In some cases you may explicitly want to keep certain files that would normally be ignored. For example, you may have hidden files like `.nojekyll` to prevent Jekyll processing, or `.htaccess` and `.htpasswd` for access control. You can keep such files in the build using the `keep_files` attribute. The `strict_undefined` attribute controls whether the build should silently ignore undefined template variables or raise an error when they are encountered. If `false` or undefined, undefined template variables are treated as empty strings (`''`). If `true`, the build will stop and raise an error. You can define additional attributes that will be made available as site variables to the template engine. The following is an example of a `_site.yml` file: ``` brand: Urubu reflinks: content_license: url: http://creativecommons.org/licenses/by-sa/3.0/ title: CC-BY-SA License software_license: url: http://www.gnu.org/licenses/agpl-3.0.txt title: GNU Affero General Public License markdown: url: http://daringfireball.net/projects/markdown/ title: Markdown file_ext: '.htm' # Change default file extension ('.html') link_ext: '.htm' # Change default link extension ('.html') ``` `_layouts` ---------- This directory contains the available layouts. They are used by the Jinja2 template engine to render html pages. The layout files should have the `.html` extension. `_python` --------- This directory contains Python hooks for the template engine. Project-wide reference ids ========================== Urubu has the concept of project-wide reference ids. You can use them to refer to link objects in your content and configuration. Their definition comes from two sources: * global reference ids are mapped to link objects in the `_site.yml` configuration file, as discussed earlier. * all content pages and folders objects have reference ids. Project-wide references ids live in a single namespace. For pages and folders, the id is a root-relative pathname starting with a slash `/` and without file extension. By convention, global reference ids should not start with a `/`. In your content and configuration info, you can also use relative reference ids. Urubu will resolve them depending on the file location in the project. In case of a name clash with a global reference id, you will have to disambiguate by adding pathname components. In accordance with Markdown conventions, reference ids are case-insensitive. Content files ============= Content files are Markdown files with extension `.md`. They should start with YAML front matter that defines a number of attributes, as in the following example: ``` --- title: Read me first layout: page date: 2014-01-15 --- ``` The following attributes are predefined: Attribute | Description -----------|------------ `title` | Specifies the page title. Mandatory. `layout` | Specifies the layout, without the `.html` extension, or `null`. Mandatory. `date` | Specifies the date in YYYY-MM-DD format. Optional. `tags` | A tag or list of tags for the content. `saveas` | Allows overriding of the output filename. The `layout` attribute is mandatory, but can be given a `null` value. This is useful when the page content is used by other pages, but no html output is required for the page itself. In addition, you can add arbitrary user-defined attributes. All attributes are made available as page object attributes to the template engine. Markdown in attributes ====================== Optionally, you can use markdown format in front matter attributes. Markdown processing is enabled by adding a `.md` suffix to the attribute. The resulting html code will be stored in a synthesized attribute without the `.md` suffix. For example: ``` --- title: layout: page summary.md: | A summary of the page items as a list: * item 1 * item 2 * item 3 --- ``` After processing, the page object will have a `summary` attribute with the html code. Index files =========== Index files with basename `index.md` are a special kind of content files. They are used to specify the attributes and the content of a directory. There are two options to specify the content, explicitly with the `content` attribute or implicitly using the `order` attribute. Attribute | Description -----------|------------ `content` | Defines the content explicitly as a list of reference ids or local link objects. `order` | Defines the attribute by which the content in the directory should be ordered. `reverse` | Optional boolean attribute defines reverse order or not. Default is `false`. `content` and `order` are mutually exclusive; you should use one of the two options. A local link object is a mapping with either a `url` key to an url, or a `ref` key to a reference id as mandatory items. In addtion, you can specify a title with a `title` key. The ordering attribute can be predefined or user-defined, but it should be specified in each content file in the directory. As an example, you can specify that the content of a directory should be ordered as blog by the following front matter in the index file: ``` --- title: Blog layout: blog_index order: date reverse: true --- ``` Tag directory ============= The optional top-level directory called `tag` has a predefined meaning. Urubu uses the corresponding folder in the build to hold the tag-related content view that it generates automatically. You can use the index file to set attributes such as the `layout`. However, the content will be generated by Urubu automatically and needs not be set. ================================================ FILE: doc/manual/templates.md ================================================ --- title: Templates layout: page pager: true author: Jan Decaluwe --- Overview ======== Templates define the html layout for a particular page type. In a template you can mix plain html with control structures and variable interpolation. The html page is generated by evaluating the template with the appropriate evaluation context, provided by Urubu. Templates are part of the website project setup. If you are a content contributor, you may not have to worry about them. All you have to do is specify the appropriate layout name in the YAML front matter of your content files. In general, it is better to do programming in Python code. However, for the purpose of generation of pages in a format such as html, this is not very practical. Therefore, a template contains both html and programming constructs. Template programming is good for common tasks like the following: * iteration over a list of items * testing whether an item is defined * filtering items, possibly with user-defined filters * comparing the loop item object with the current object, to check whether it is active Urubu interacts with templates by providing an evaluation context with the appropriate objects. The goal is to make the job of the templates as easy as possible with ready-to-use object attributes. The template library ==================== Urubu uses the [jinja2] templating language library. Jinja2 has great [documentation][jinja2_docs] and you should check it out when using templates in Urubu. [jinja2_docs]: http://jinja2.pocoo.org/docs A great feature of Jinja2 is template inheritance. With this technique, you can easily generate small variations of a parent template. Link objects ============ Description ----------- Link objects are the primary objects that you use in templates. They come in a number of flavours: Link object | Description -------------------|--------------- global link object | Defined in the `_site.yml` file. local link object | Defined locally in the `content` attribute of an index file. folder object | Corresponds to a project subdirectory. page object | Corresponds to a Markdown content file. tag folder object | Dedicated folder for content ordered by tag. tag object | Represents content corresponding to a specific tag. Attributes ---------- Link objects have attributes. The defined attributes depend on the type of the link object. The following attributes are common to **all link objects**: Attribute | Description ---------------|--------------------------- `url` | The url of the object. `title` | The title of the object. **All link objects except local link objects** also have an `id` attribute: Attribute | Description ---------------|--------------------------- `id` | The unique id by which the object is known in the project. **Folder and page objects** have the following attributes: Attribute | Description ---------------|--------------------------- `fn` | The pathname of the file or directory corresponding the object. `components` | The components of the object's pathname, without file extension, as a list. `mdate` | Modification date **Folder objects** also have a `content` attribute: Attribute | Description ---------------|--------------------------- `content` | The content of the folder as a list of page & folder objects. In addition, all attributes specified in the YAML front matter of the corresponding index file will be available as attributes of the folder object. **Page objects** have the following additional attributes: Attribute | Description ---------------|--------------------------- `layout` | The template to render the object as a html file. `body` | The page content in html. `toc` | The table of contents of the page as an unordered html list. `breadcrumbs` | Breadcrumbs as a list. The current page object is at position 0, the containing folder objects are at the higher positions. `prev` | The previous page object in the content, or `None` if there is none `next` | The next page object in the content, or `None` if there is none In addition, all attributes specified in the YAML front matter of the corresponding content file are available as attributes of the page object. Index pages ----------- Index pages are associated with `index.md` files. They are special in the sense that they define the attributes and the content of a folder. Therefore, they have the same `content` attribute as the corresponding folder object. Tag objects ----------- Tag objects are inferred by Urubu automatically. They list the content corresponding to a tag. {% raw %} Attribute | Description ---------------|--------------------------- `id` | `/tag/{{tag}}` `components` | `[tag, {{tag}}]` `title` | `tag` `tag` | `tag` `layout` | `tag` `content` | List of page & folder objects corresponding to `tag`. {% endraw %} The tag content is ordered by date, most recent first. If the date is not defined, the modification date is used as a fallback (`mdate` attribute). The layout name is predefined to `tag`. You have to provide the `tag.html` template to trigger the rendering of tag objects. In the simplest case, it may be sufficient to inherit from a general index layout. Tag folder object ----------------- The tag folder object is a special top-level folder whose `id` is `/tag`. Urubu infers tag-related content for this folder automatically. You can optionally create the corresponding directory in the source code, and use the index file to set attributes such as the `layout`. In any case, Urubu will create the object if tags are used, and infer the `content` attribute. Attribute | Description ---------------|--------------------------- `id` | `/tag` `components` | `[tag]` `content` | A list of tag objects, inferred by Urubu. The content is ordered according to the content size of tag objects, the largest one first. Context variables ================= Urubu makes the context available to templates with two context variables. `site` ------ This variable holds site-wide information. It has one predefined attribute: Attribute | Description ---------------|--------------------------- `reflinks` | A mapping from all reference ids to link objects. Note that the id of the root object is `/`. Starting from there, you can traverse the whole site. In addition, all the attributes specified in the `_site.yml` file will be available as attributes of the `site` variable. `this` ------ This variable holds the current page or tag object. ================================================ FILE: doc/manual/templating-in-pages.md ================================================ --- title: Templating constructs in pages layout: page pager: true author: Jan Decaluwe --- {% from 'util.html' import open, done, fa, figure %} Overview ======== Writing in Markdown is great, but sometimes you run into limitations. For those cases, Urubu supports a feature gratefully borrowed from [jekyll]: using templating constructs in content pages. Basically, all content pages are processed by the templating engine before going to the Markdown processor. The full power of [jinja2] is thus available in your content pages. The usage of templating constructs in content pages is best explained with examples. Therefore, we will start with some examples, and review the concepts afterwards. Example usage ============= Task list icons --------------- Suppose you want to emulate [github] style task lists, as follows: * {{ open }} Task 1 * {{ done }} Task 2 * {{ open }} Task 1 An icon is used to show whether a task is still open or not. We can support this by defining well-named reusable variables in a dedicated template file, as follows: ``` {% raw %} {% set open = '' %} {% set done = '' %} {% endraw %} ``` Variables `open` and `done` now hold HTML code that refers to icons. In these examples, I use the [font-awesome] icon library. You will need to add the appropriate reference to the icon stylesheet in your base template. Suppose these variables are defined in the file `_layouts/util.html`. We can import them in any content page as follows: ``` {% raw %} {% from 'util.html' import open, done %} {% endraw %} ``` Note that Urubu knows to look up `util.html` in the `_layouts/` directory, because that is where templates should be located. Within the content page, we can use the variables as follows, to get the result as above: ``` {% raw %} * {{ open }} Task 1 * {{ done }} Task 2 * {{ open }} Task 1 {% endraw %} ``` General icon interface ---------------------- Suppose you want a more general interface to icons, so that you can easily refer to any icon by name. This can be done with a Jinja2 macro. A macro is like a function that can take parameters: ``` {% raw %} {% macro fa(name, class='') %} {% endmacro %} {% endraw %} ``` Again, we can import the macro `fa` in content pages: ``` {% raw %} {% from 'util.html' import fa %} {% endraw %} ``` Then we can use it as follows, for example to refer to the Github icon: ``` {% raw %} {{ fa('github') }} {% endraw %} ``` This gives the following result: {{ fa('github') }} We can pass additional CSS classes via the optional `class` parameter. The following example gets the alternative Github icon in twice the basic size: ``` {% raw %} {{ fa('github-alt', 'fa-2x') }} {% endraw %} ``` This gives the following result: {{ fa('github-alt', 'fa-2x') }} Figure ------ Standard Markdown does not support the HTML5 `
` tag, and the related `
` tag to add captions. We can support this with the following macro: ``` {% raw %} {% macro figure(fn, caption='') %}
{{caption}} {% if caption %}
{{caption}}
{% endif %}
{% endmacro %} {% endraw %} ``` This macro assumes that images will be placed in an `img/` directory. In addition, it makes the image responsive using a Bootstrap class, and centers the optional caption. Again, we can use the macro by importing: ``` {% raw %} {% from 'util.html' import figure %} {% endraw %} ``` This is an example usage: ``` {% raw %} {{ figure('urubu.jpg', "An Urubu - a brazilian vulture") }} {% endraw %} ``` This gives the following result: {{ figure('urubu.jpg', "An Urubu - a brazilian vulture") }} Templating concepts =================== Template processing is done first --------------------------------- The examples illustrate how you can use template variables and macros to construct HTML code. However, it is important to understand that template processing is done first, before Markdown processing (for good reasons). Thus, the HTML code from variables and macros first becomes part of Markdown source code. This works well because Markdown is designed to handle HTML transparently. Full template power available ----------------------------- The examples demonstrate the use of variables, macros, and imports. This is merely the beginning: in fact, the full power of Jinja2 templates is available. This is a vast subject. To learn what is possible, see the [Jinja2 Template Designer Documentation][jinja2_templates]. Context variables ----------------- When Urubu invokes template processing on a page, it automatically passes certain context variables. This works exactly like for regular templates, as described in [/manual/templates#Context Variables]. Basically, variable `this` provides access to the page attributes, and variable `site` provides access to the global site attributes. Template delimiters ------------------- Template support introduces new delimiters as follows: {% raw -%} * `{# ... #}` for comments not included in the output * `{{ ... }}` for expressions, to print to the output * `{% ... %}` for statements {% endraw %} These delimiters deserve some attention. {# Now commenting about comments #} First, the comment delimiters are interesting because they add a functionality that is not available in Markdown: comments that will not show up in the output. Secondly, as always with delimiters, there is the problem of how to escape them if you want to use them literally in source code, without interpretation. For an inline literal or snippet you can use literal expressions. For example, to get `{{ '{{' }}` you can write {% raw %} `{{ '{{' }}` {% endraw %}. For a larger section, you can mark a block *raw*. For example, to get the list shown earlier in this section, you can write: ``` {{ '{% raw %}' }} {% raw -%} * `{# ... #}` for comments not included in the output * `{{ ... }}` for expressions, to print to the output * `{% ... %}` for statements {% endraw %} {{ '{% endraw %}' }} ``` [jinja2_templates]: http://jinja.pocoo.org/docs/dev/templates ================================================ FILE: doc/more/about.md ================================================ --- title: About this site layout: page date: 2014-01-10 --- Author ====== The Urubu software is written by [jandecaluwe]. License ======= The Urubu software is licensed under the [software_license]. The content on this documentation website is licensed under the [content_license]. Development =========== The Urubu software is developed on [github] in the [urubu-repo]. The documentation is developed as a website in a `gh-pages` branch in the same repo. It can be accessed from the custom domain [urubu.jandecaluwe.com] but it is hosted on [GitHub Pages]. [urubu.jandecaluwe.com]: http://urubu.jandecaluwe.com [Github Pages]: http://pages.github.com Theme ===== The theme on this website uses the [bootstrap] framework, and is based on stock [bootstrap]. Trivia ====== An urubu is a brazilian vulture. [Urubu][Urubu_album] is also the 10th album of Antonio Carlos Jobim, one of my favorite song composers. [Urubu_album]: http://en.wikipedia.org/wiki/Urubu_(album) ================================================ FILE: doc/more/index.md ================================================ --- title: More layout: index dropdown: true content: - ref: urubu-repo title: GitHub repository - sites - about --- ================================================ FILE: doc/more/sites.md ================================================ --- title: Websites powered by Urubu layout: simple_page --- I created Urubu to solve a personal problem: how to create and maintain websites for my projects. I open-sourced it "in the hope it can be useful". On this page I list a number of websites that are powered by Urubu. By others ========= [Sigasi Insights][sigasi] - Documentation for Sigasi's tools. [Leonardo Uieda][leouieda] - Website about Leonardo's professional activities. [PINGA lab][pinga] - Site for the PINGA lab, a research group studying inverse problems in geophysics. For others, by me ================= [Vlaamse sofrologen][sofro] - Site of the flemish sophrologists (in Dutch) [Troca Vins Naturels][troca] - Natural wines MyHDL ===== [myhdl_site] - all about MyHDL, for users [dev_myhdl_site] - info for MyHDL developers Urubu ===== [urubu-quickstart] - the Quickstart companion site for Urubu [urubu] - this site Personal ======== [Jan Decaluwe][jan] My site about professional activities [Jan Decaluwe / Music][janmusic] My music projects [Jan Decaluwe / Opinions][janopinion] My opinions, in Dutch [sigasi]: http://insights.sigasi.com [leouieda]: http://www.leouieda.com/ [pinga]: http://www.pinga-lab.org/ [sofro]: http://www.vlaamsesofrologen.be [jan]: http://www.jandecaluwe.com [janmusic]: http://music.jandecaluwe.com [janopinion]: http://nl.jandecaluwe.com [troca]: http://www.troca-vn.be ================================================ FILE: doc/news/2014-01-12.md ================================================ --- title: Urubu 0.1 released layout: page date: 2014-01-12 --- Introducing Urubu, a Python-based micro CMS for static websites. Read about [the rationale behind it][rationale]. [rationale]: http://www.jandecaluwe.com/blog/i-dont-like-blogs.html ================================================ FILE: doc/news/2014-01-22.md ================================================ --- title: Urubu 0.2 released layout: page date: 2014-01-22 --- This release adds support for github-style task lists. ================================================ FILE: doc/news/2014-02-15.md ================================================ --- title: Urubu 0.2.1 released layout: page date: 2014-02-15 --- This is a bug fix release. ================================================ FILE: doc/news/2014-02-27.md ================================================ --- title: Urubu 0.3 released layout: page date: 2014-02-27 --- This release adds markdown support for front-matter attributes. [Read more »](/manual/structure.html#markdown-in-attributes) ================================================ FILE: doc/news/2014-03-18.md ================================================ --- title: Urubu 0.3.1 released layout: page date: 2014-03-18 --- This is a bug-fix release. ================================================ FILE: doc/news/2014-05-25.md ================================================ --- title: Urubu 0.4 and Urubu Quickstart released layout: page date: 2014-05-25 --- Release features: - Run `urubu serve` from the top-level project directory. - [Programmable file extensions][/manual/structure] for site pages - Introducing [urubu-quickstart]: a quick way to set up a new Urubu project. ================================================ FILE: doc/news/2014-09-08.md ================================================ --- title: Urubu 0.5 released layout: page date: 2014-09-08 --- Urubu 0.5 introduces tag support. Read [my blog post][post] for an introduction. [post]: http://www.jandecaluwe.com/blog/tag_support_urubu.html ================================================ FILE: doc/news/2015-01-28.md ================================================ --- title: Urubu 0.6 released layout: page date: 2015-01-28 --- Urubu 0.6 improves on wiki links: now you can link to a location within a page. Read [my blog post][post] for more info. [post]: http://www.jandecaluwe.com/blog/urubu-0-6.html ================================================ FILE: doc/news/2015-03-07.md ================================================ --- title: "Urubu 0.7: Python 3 support, baseurl option" layout: page date: 2015-03-07 --- Urubu 0.7 adds features that make it more flexible to use. First, the release adds Python 3 support, from a single codebase. You can use Python 2.7 or Python 3.4. Second, there is now a `baseurl` option to add a prefix to generated local URLs. [More info »][/manual/structure#_siteyml]. On the other hand, the checklist extension has been removed as it caused issues with reference id resolution. ================================================ FILE: doc/news/2015-11-22.md ================================================ --- title: "Urubu 0.8 released" layout: page date: 2015-11-22 --- Release highlights: * the `urubu` serve command automatically takes the `baseurl` option into account (Pull request #27). * when an undefined anchor is referred to in a page, a warning is generated, just like for references to undefined pages (Issue #30). * the `layout` attribute can be assigned `null`. In this way the page content can be used by other pages, but no html is generated for the page itself. In addition, a significant effort was put into development robustness. In particular, a regression test suite has been added. This is based on `py.test` and `tox`, so that both Python 2.7 and 3.4 are verified. ================================================ FILE: doc/news/2015-12-15.md ================================================ --- title: "Urubu 0.9.0 released" layout: page date: 2015-12-15 --- This release adds support for Tipue Search, an open source search solution based on Javascript in the browser. Read more in the chapter [/manual/search] in the manual. ================================================ FILE: doc/news/2016-01-01.md ================================================ --- title: "Urubu 1.0.0 released" layout: page date: 2016-01-01 --- This release adds support for the `process_info` Python hook. This hook provides a powerful way to assist in templating. Basically, it provides full Python power to inspect, verify, modify, and add page attributes. For example, you can use it to define a default `layout`, or a specific `layout` for pages in a certain directory. Read more in the manual: [/manual/hooks#The process_info hook]. There is also a new `keep_files` configuration attribute, that lets you preserve files that would otherwise be ignored. See the [documentation][/manual/structure#_siteyml]. ================================================ FILE: doc/news/2016-01-10.md ================================================ --- title: "Urubu 1.1.0 released" layout: page date: 2016-01-10 --- This release adds experimental support for the ` tag. Read more in the manual: [/manual/extensions#Support for the mark tag] and in [this blog post][post]. [post]: http://www.jandecaluwe.com/blog/mark-tag-support.html ================================================ FILE: doc/news/2016-02-12.md ================================================ --- title: "Urubu 1.2.0 released" layout: page date: 2016-02-12 --- The highlight of this release is support for [/manual/templating-in-pages]. ================================================ FILE: doc/news/2016-11-14.md ================================================ --- title: "Urubu 1.3.0 released" layout: page date: 2016-11-14 --- Highlights: * Add posibility to override output filename. (#51). See the `saveas` attribute in the [manual][/manual/structure#Content Files]. An example usage, see [/faq/sitemap]. * The `urubu serve` command is more secure. This is transparent to the user (#49). * Added option for jinja2 to fail on undefined vars (#47). See the `strict_undefined` attribute in the [manual][/manual/structure#_siteyml]. ================================================ FILE: doc/news/2018-08-15.md ================================================ --- title: "Urubu 1.3.1 released" layout: page date: 2018-08-15 --- Maintenance release: bug fixes and small enhancements to existing features. See the git log and the manual. ================================================ FILE: doc/news/2024-12-30.md ================================================ --- title: "Urubu 1.4.0 released" layout: page date: 2024-12-30 --- Python3 only. ================================================ FILE: doc/news/2026-03-30.md ================================================ --- title: "Urubu 1.4.1 released" layout: page date: 2026-03-30 --- Maintenance release: added test dependencies to setup.py, removed Python 2 compatibility layer, and relaxed the Markdown version pin to >= 3.0. ================================================ FILE: doc/news/index.md ================================================ --- title: Newsfeed layout: newsfeed order: date reverse: true --- ================================================ FILE: doc/search.md ================================================ --- title: Search results layout: search ---
================================================ FILE: doc/start.md ================================================ --- title: Overview layout: page pager: true date: 2014-01-10 --- What is Urubu? ============== Urubu is _a tool to build static websites_. The following sections will help you to decide whether it is the right tool for you. Static versus dynamic ===================== A static website is the simple case. It consists of a set of fixed pages. The only job of the web server is to serve the page that you request. The opposite is a dynamic website. In this case, you interact with a program on the web server. Depending on the request, the web server program generates a response page on the fly. Clearly, a dynamic website supports a much more interactive and sophisticated web experience. If this is what you need, you should consider a full-fledged CMS or CMS generator tool. There is a [wide choice][cms_list] of them in the Python world. [cms_list]: https://wiki.python.org/moin/ContentManagementSystems On the other hand, a static website is great for performance, security and maintainability. If you don't need the overhead of a dynamic CMS, it is a wise choice. Why a tool? =========== One option is to write a static website by hand by editing the html code for each page. However, this quickly becomes an unpractical solution for two reasons. First, writing html is no fun. The markup overhead is error prone and makes it difficult to read the actual content. In Urubu, you use [markdown] for authoring instead. Markdown is an almost zero overhead input format and feels like a natural way to write content in plain text. Secondly, html pages have a lot of non-content overhead that is equal or similar across pages, such as navigation info. Duplicating and maintaining this info manually is error prone and time consuming. In Urubu, you use templates (also known as layouts) instead. They make it easy to define the common html structure of a set of similar pages. Why Urubu? ========== There is no shortage of static web site generators, including a lot of [Python solutions][tool_list]. However, these tools are typically blog oriented. If your website is primarily a blog, with content in reverse chronological order and with good support for tagging and archiving, there are many other solutions than Urubu. [tool_list]: https://wiki.python.org/moin/PythonBlogSoftware#Static On the other hand, _if you view your website as a set of logically connected content pages, Urubu is an excellent choice_. Urubu makes it it easy to define a good navigation structure, so that a user is never "lost". This is especially important for technical content. Of course, you can also include a blog in an Urubu site. Within a folder, you can specify how the content should be ordered using an arbitrary key. For a blog, this would be reverse order by date. Urubu's ideal use case ====================== If you would like to develop a website like a software project, you will feel at home with Urubu. For example, you can maintain an Urubu site in a git or mercurial repository and use the workflows that these systems enable. For example, you can collaborate on [github] or [bitbucket] through [pull requests]. Also, deployment can be as straightforward as pushing to an upstream repository. [pull requests]: https://help.github.com/articles/using-pull-requests ================================================ FILE: doc/tipuesearch/tipuesearch.css ================================================ /* Tipue Search 5.0 Copyright (c) 2015 Tipue Tipue Search is released under the MIT License http://www.tipue.com/search */ /* #tipue_search_input { font: 13px/1.6 'open sans', sans-serif; color: #333; padding: 12px 12px 12px 40px; width: 170px; border: 1px solid #e2e2e2; border-radius: 0; -moz-appearance: none; -webkit-appearance: none; box-shadow: none; outline: 0; margin: 0; background: #fff url('img/search.png') no-repeat 15px 15px; } */ #tipue_search_content { max-width: 650px; padding-top: 15px; margin: 0; } #tipue_search_warning { font: 300 15px/1.6 'Open Sans', sans-serif; color: #555; margin: 7px 0; } #tipue_search_warning a { color: #396; text-decoration: none; } #tipue_search_warning a:hover { color: #555; } #tipue_search_results_count { font: 300 15px/1.7 'Open Sans', sans-serif; color: #555; } .tipue_search_content_title { font: 300 21px/1.7 'Open Sans', sans-serif; margin-top: 23px; } .tipue_search_content_title a { color: #333; text-decoration: none; } .tipue_search_content_title a:hover { color: #555; } .tipue_search_content_url { font: 300 14px/1.9 'Open Sans', sans-serif; word-wrap: break-word; hyphens: auto; } .tipue_search_content_url a { color: #396; text-decoration: none; } .tipue_search_content_url a:hover { color: #555; } .tipue_search_content_text { font: 300 15px/1.6 'Open Sans', sans-serif; color: #555; word-wrap: break-word; hyphens: auto; margin-top: 3px; } .tipue_search_content_debug { font: 300 13px/1.6 'Open Sans', sans-serif; color: #555; margin: 5px 0; } .h01 { color: #333; font-weight: 400; } #tipue_search_foot { margin: 51px 0 21px 0; } #tipue_search_foot_boxes { padding: 0; margin: 0; font: 12px 'Open Sans', sans-serif; } #tipue_search_foot_boxes li { list-style: none; margin: 0; padding: 0; display: inline; } #tipue_search_foot_boxes li a { padding: 10px 17px 11px 17px; background-color: #fff; border: 1px solid #e2e2e2; border-radius: 1px; color: #333; margin-right: 7px; text-decoration: none; text-align: center; } #tipue_search_foot_boxes li.current { padding: 10px 17px 11px 17px; background: #f6f6f6; border: 1px solid #e2e2e2; border-radius: 1px; color: #333; margin-right: 7px; text-align: center; } #tipue_search_foot_boxes li a:hover { background: #f6f6f6; } /* spinner */ .tipue_search_spinner { padding: 31px 0; width: 50px; height: 28px; } .tipue_search_spinner > div { background-color: #777; height: 100%; width: 3px; display: inline-block; margin-right: 2px; -webkit-animation: stretchdelay 1.2s infinite ease-in-out; animation: stretchdelay 1.2s infinite ease-in-out; } .tipue_search_spinner .tipue_search_rect2 { -webkit-animation-delay: -1.1s; animation-delay: -1.1s; } .tipue_search_spinner .tipue_search_rect3 { -webkit-animation-delay: -1.0s; animation-delay: -1.0s; } @-webkit-keyframes stretchdelay { 0%, 40%, 100% { -webkit-transform: scaleY(0.4) } 20% { -webkit-transform: scaleY(1.0) } } @keyframes stretchdelay { 0%, 40%, 100% { transform: scaleY(0.4); -webkit-transform: scaleY(0.4); } 20% { transform: scaleY(1.0); -webkit-transform: scaleY(1.0); } } ================================================ FILE: doc/tipuesearch/tipuesearch.css.in ================================================ /* Tipue Search 5.0 Copyright (c) 2015 Tipue Tipue Search is released under the MIT License http://www.tipue.com/search */ #tipue_search_input { font: 13px/1.6 'open sans', sans-serif; color: #333; padding: 12px 12px 12px 40px; width: 170px; border: 1px solid #e2e2e2; border-radius: 0; -moz-appearance: none; -webkit-appearance: none; box-shadow: none; outline: 0; margin: 0; background: #fff url('img/search.png') no-repeat 15px 15px; } #tipue_search_content { max-width: 650px; padding-top: 15px; margin: 0; } #tipue_search_warning { font: 300 15px/1.6 'Open Sans', sans-serif; color: #555; margin: 7px 0; } #tipue_search_warning a { color: #396; text-decoration: none; } #tipue_search_warning a:hover { color: #555; } #tipue_search_results_count { font: 300 15px/1.7 'Open Sans', sans-serif; color: #555; } .tipue_search_content_title { font: 300 21px/1.7 'Open Sans', sans-serif; margin-top: 23px; } .tipue_search_content_title a { color: #333; text-decoration: none; } .tipue_search_content_title a:hover { color: #555; } .tipue_search_content_url { font: 300 14px/1.9 'Open Sans', sans-serif; word-wrap: break-word; hyphens: auto; } .tipue_search_content_url a { color: #396; text-decoration: none; } .tipue_search_content_url a:hover { color: #555; } .tipue_search_content_text { font: 300 15px/1.6 'Open Sans', sans-serif; color: #555; word-wrap: break-word; hyphens: auto; margin-top: 3px; } .tipue_search_content_debug { font: 300 13px/1.6 'Open Sans', sans-serif; color: #555; margin: 5px 0; } .h01 { color: #333; font-weight: 400; } #tipue_search_foot { margin: 51px 0 21px 0; } #tipue_search_foot_boxes { padding: 0; margin: 0; font: 12px 'Open Sans', sans-serif; } #tipue_search_foot_boxes li { list-style: none; margin: 0; padding: 0; display: inline; } #tipue_search_foot_boxes li a { padding: 10px 17px 11px 17px; background-color: #fff; border: 1px solid #e2e2e2; border-radius: 1px; color: #333; margin-right: 7px; text-decoration: none; text-align: center; } #tipue_search_foot_boxes li.current { padding: 10px 17px 11px 17px; background: #f6f6f6; border: 1px solid #e2e2e2; border-radius: 1px; color: #333; margin-right: 7px; text-align: center; } #tipue_search_foot_boxes li a:hover { background: #f6f6f6; } /* spinner */ .tipue_search_spinner { padding: 31px 0; width: 50px; height: 28px; } .tipue_search_spinner > div { background-color: #777; height: 100%; width: 3px; display: inline-block; margin-right: 2px; -webkit-animation: stretchdelay 1.2s infinite ease-in-out; animation: stretchdelay 1.2s infinite ease-in-out; } .tipue_search_spinner .tipue_search_rect2 { -webkit-animation-delay: -1.1s; animation-delay: -1.1s; } .tipue_search_spinner .tipue_search_rect3 { -webkit-animation-delay: -1.0s; animation-delay: -1.0s; } @-webkit-keyframes stretchdelay { 0%, 40%, 100% { -webkit-transform: scaleY(0.4) } 20% { -webkit-transform: scaleY(1.0) } } @keyframes stretchdelay { 0%, 40%, 100% { transform: scaleY(0.4); -webkit-transform: scaleY(0.4); } 20% { transform: scaleY(1.0); -webkit-transform: scaleY(1.0); } } ================================================ FILE: doc/tipuesearch/tipuesearch.js ================================================ /* Tipue Search 5.0 Copyright (c) 2015 Tipue Tipue Search is released under the MIT License http://www.tipue.com/search */ (function($) { $.fn.tipuesearch = function(options) { var set = $.extend( { 'show' : 7, 'newWindow' : false, 'showURL' : true, 'showTitleCount' : true, 'minimumLength' : 3, 'descriptiveWords' : 25, 'highlightTerms' : true, 'highlightEveryTerm' : false, 'mode' : 'static', 'liveDescription' : '*', 'liveContent' : '*', 'contentLocation' : 'tipuesearch/tipuesearch_content.json', 'debug' : false }, options); return this.each(function() { var tipuesearch_in = { pages: [] }; $.ajaxSetup({ async: false }); var tipuesearch_t_c = 0; if (set.mode == 'live') { for (var i = 0; i < tipuesearch_pages.length; i++) { $.get(tipuesearch_pages[i]) .done(function(html) { var cont = $(set.liveContent, html).text(); cont = cont.replace(/\s+/g, ' '); var desc = $(set.liveDescription, html).text(); desc = desc.replace(/\s+/g, ' '); var t_1 = html.toLowerCase().indexOf(''); var t_2 = html.toLowerCase().indexOf('', t_1 + 7); if (t_1 != -1 && t_2 != -1) { var tit = html.slice(t_1 + 7, t_2); } else { var tit = tipuesearch_string_1; } tipuesearch_in.pages.push( { "title": tit, "text": desc, "tags": cont, "url": tipuesearch_pages[i] }); }); } } if (set.mode == 'json') { $.getJSON(set.contentLocation) .done(function(json) { tipuesearch_in = $.extend({}, json); }); } if (set.mode == 'static') { tipuesearch_in = $.extend({}, tipuesearch); } var tipue_search_w = ''; if (set.newWindow) { tipue_search_w = ' target="_blank"'; } function getURLP(name) { return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search)||[,""])[1].replace(/\+/g, '%20')) || null; } if (getURLP('q')) { $('#tipue_search_input').val(getURLP('q')); getTipueSearch(0, true); } $(this).keyup(function(event) { if(event.keyCode == '13') { getTipueSearch(0, true); } }); function getTipueSearch(start, replace) { $('#tipue_search_content').hide(); $('#tipue_search_content').html('
'); $('#tipue_search_content').show(); var out = ''; var results = ''; var show_replace = false; var show_stop = false; var standard = true; var c = 0; found = []; var d = $('#tipue_search_input').val().toLowerCase(); d = $.trim(d); if ((d.match("^\"") && d.match("\"$")) || (d.match("^'") && d.match("'$"))) { standard = false; } if (standard) { var d_w = d.split(' '); d = ''; for (var i = 0; i < d_w.length; i++) { var a_w = true; for (var f = 0; f < tipuesearch_stop_words.length; f++) { if (d_w[i] == tipuesearch_stop_words[f]) { a_w = false; show_stop = true; } } if (a_w) { d = d + ' ' + d_w[i]; } } d = $.trim(d); d_w = d.split(' '); } else { d = d.substring(1, d.length - 1); } if (d.length >= set.minimumLength) { if (standard) { if (replace) { var d_r = d; for (var i = 0; i < d_w.length; i++) { for (var f = 0; f < tipuesearch_replace.words.length; f++) { if (d_w[i] == tipuesearch_replace.words[f].word) { d = d.replace(d_w[i], tipuesearch_replace.words[f].replace_with); show_replace = true; } } } d_w = d.split(' '); } var d_t = d; for (var i = 0; i < d_w.length; i++) { for (var f = 0; f < tipuesearch_stem.words.length; f++) { if (d_w[i] == tipuesearch_stem.words[f].word) { d_t = d_t + ' ' + tipuesearch_stem.words[f].stem; } } } d_w = d_t.split(' '); for (var i = 0; i < tipuesearch_in.pages.length; i++) { var score = 0; var s_t = tipuesearch_in.pages[i].text; for (var f = 0; f < d_w.length; f++) { var pat = new RegExp(d_w[f], 'gi'); if (tipuesearch_in.pages[i].title.search(pat) != -1) { var m_c = tipuesearch_in.pages[i].title.match(pat).length; score += (20 * m_c); } if (tipuesearch_in.pages[i].text.search(pat) != -1) { var m_c = tipuesearch_in.pages[i].text.match(pat).length; score += (20 * m_c); } if (set.highlightTerms) { if (set.highlightEveryTerm) { var patr = new RegExp('(' + d_w[f] + ')', 'gi'); } else { var patr = new RegExp('(' + d_w[f] + ')', 'i'); } s_t = s_t.replace(patr, "$1"); } if (tipuesearch_in.pages[i].tags.search(pat) != -1) { var m_c = tipuesearch_in.pages[i].tags.match(pat).length; score += (10 * m_c); } if (tipuesearch_in.pages[i].url.search(pat) != -1) { score += 20; } if (score != 0) { for (var e = 0; e < tipuesearch_weight.weight.length; e++) { if (tipuesearch_in.pages[i].url == tipuesearch_weight.weight[e].url) { score += tipuesearch_weight.weight[e].score; } } } if (d_w[f].match('^-')) { pat = new RegExp(d_w[f].substring(1), 'i'); if (tipuesearch_in.pages[i].title.search(pat) != -1 || tipuesearch_in.pages[i].text.search(pat) != -1 || tipuesearch_in.pages[i].tags.search(pat) != -1) { score = 0; } } } if (score != 0) { found.push( { "score": score, "title": tipuesearch_in.pages[i].title, "desc": s_t, "url": tipuesearch_in.pages[i].url }); c++; } } } else { for (var i = 0; i < tipuesearch_in.pages.length; i++) { var score = 0; var s_t = tipuesearch_in.pages[i].text; var pat = new RegExp(d, 'gi'); if (tipuesearch_in.pages[i].title.search(pat) != -1) { var m_c = tipuesearch_in.pages[i].title.match(pat).length; score += (20 * m_c); } if (tipuesearch_in.pages[i].text.search(pat) != -1) { var m_c = tipuesearch_in.pages[i].text.match(pat).length; score += (20 * m_c); } if (set.highlightTerms) { if (set.highlightEveryTerm) { var patr = new RegExp('(' + d + ')', 'gi'); } else { var patr = new RegExp('(' + d + ')', 'i'); } s_t = s_t.replace(patr, "$1"); } if (tipuesearch_in.pages[i].tags.search(pat) != -1) { var m_c = tipuesearch_in.pages[i].tags.match(pat).length; score += (10 * m_c); } if (tipuesearch_in.pages[i].url.search(pat) != -1) { score += 20; } if (score != 0) { for (var e = 0; e < tipuesearch_weight.weight.length; e++) { if (tipuesearch_in.pages[i].url == tipuesearch_weight.weight[e].url) { score += tipuesearch_weight.weight[e].score; } } } if (score != 0) { found.push( { "score": score, "title": tipuesearch_in.pages[i].title, "desc": s_t, "url": tipuesearch_in.pages[i].url }); c++; } } } if (c != 0) { if (set.showTitleCount && tipuesearch_t_c == 0) { var title = document.title; document.title = '(' + c + ') ' + title; tipuesearch_t_c++; } if (show_replace == 1) { out += '
' + tipuesearch_string_2 + ' ' + d + '. ' + tipuesearch_string_3 + ' ' + d_r + '
'; } if (c == 1) { out += '
' + tipuesearch_string_4 + '
'; } else { c_c = c.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); out += '
' + c_c + ' ' + tipuesearch_string_5 + '
'; } found.sort(function(a, b) { return b.score - a.score } ); var l_o = 0; for (var i = 0; i < found.length; i++) { if (l_o >= start && l_o < set.show + start) { out += ''; if (set.debug) { out += '
Score: ' + found[i].score + '
'; } if (set.showURL) { var s_u = found[i].url.toLowerCase(); if(s_u.indexOf('http://') == 0) { s_u = s_u.slice(7); } out += ''; } if (found[i].desc) { var t = found[i].desc; var t_d = ''; var t_w = t.split(' '); if (t_w.length < set.descriptiveWords) { t_d = t; } else { for (var f = 0; f < set.descriptiveWords; f++) { t_d += t_w[f] + ' '; } } t_d = $.trim(t_d); if (t_d.charAt(t_d.length - 1) != '.') { t_d += ' ...'; } out += '
' + t_d + '
'; } } l_o++; } if (c > set.show) { var pages = Math.ceil(c / set.show); var page = (start / set.show); out += '
    '; if (start > 0) { out += '
  • ' + tipuesearch_string_6 + '
  • '; } if (page <= 2) { var p_b = pages; if (pages > 3) { p_b = 3; } for (var f = 0; f < p_b; f++) { if (f == page) { out += '
  • ' + (f + 1) + '
  • '; } else { out += '
  • ' + (f + 1) + '
  • '; } } } else { var p_b = page + 2; if (p_b > pages) { p_b = pages; } for (var f = page - 1; f < p_b; f++) { if (f == page) { out += '
  • ' + (f + 1) + '
  • '; } else { out += '
  • ' + (f + 1) + '
  • '; } } } if (page + 1 != pages) { out += '
  • ' + tipuesearch_string_7 + '
  • '; } out += '
'; } } else { out += '
' + tipuesearch_string_8 + '
'; } } else { if (show_stop) { out += '
' + tipuesearch_string_8 + '. ' + tipuesearch_string_9 + '
'; } else { out += '
' + tipuesearch_string_10 + '
'; if (set.minimumLength == 1) { out += '
' + tipuesearch_string_11 + '
'; } else { out += '
' + tipuesearch_string_12 + ' ' + set.minimumLength + ' ' + tipuesearch_string_13 + '
'; } } } $('#tipue_search_content').hide(); $('#tipue_search_content').html(out); $('#tipue_search_content').slideDown(200); $('#tipue_search_replaced').click(function() { getTipueSearch(0, false); }); $('.tipue_search_foot_box').click(function() { var id_v = $(this).attr('id'); var id_a = id_v.split('_'); getTipueSearch(parseInt(id_a[0]), id_a[1]); }); } }); }; })(jQuery); ================================================ FILE: doc/tipuesearch/tipuesearch_content.js ================================================ var tipuesearch = {"pages": [ {"title": "Tipue", "text": "", "tags": "jQuery HTML5 CSS", "url": "http://www.tipue.com"}, {"title": "Tipue Search, a site search engine jQuery plugin", "text": "Tipue Search is a site search engine jQuery plugin. It's free, open source, responsive and fast. Tipue Search only needs a browser that supports jQuery. It doesn't need MySQL or similar. In Static mode it doesn't even need a web server.", "tags": "JavaScript", "url": "http://www.tipue.com/search"}, {"title": "Tipue Search Documentation", "text": "Tipue Search is a site search engine jQuery plugin. It's free, open source and responsive. Tipue Search uses various modes for loading content. Static mode uses a JavaScript object, while JSON mode uses JSON. Live mode grabs content from a list of pages dynamically.", "tags": "docs", "url": "http://www.tipue.com/search/docs"}, {"title": "Tipue Search Static mode demo", "text": "Tipue Search is a site search engine jQuery plugin. This is a demo of Static mode. Enter tipue into the search box above.", "tags": "", "url": "http://www.tipue.com/search/demos/static"}, {"title": "Tipue Search Live mode demo", "text": "Tipue Search is a site search engine jQuery plugin. This is a demo of Live mode. Enter tipue into the search box above.", "tags": "", "url": "http://www.tipue.com/search/demos/live"}, {"title": "Tipue jQuery plugins Support", "text": "If you're stuck we offer a range of flexible support plans for our jQuery plugins.", "tags": "", "url": "http://www.tipue.com/support"}, {"title": "Tipr, a small and simple jQuery tooltip plugin", "text": "Tipr is a small and simple jQuery tooltip plugin. It's free and open source. Tipr displays attractive tooltips, and it's a shade under 4KB, CSS included.", "tags": "JavaScript", "url": "http://www.tipue.com/tipr"}, {"title": "The Tipue blog", "text": "An occasional blog covering CSS, web development, etc.", "tags": "HTML5", "url": "http://www.tipue.com/?d=2"}, {"title": "About Tipue", "text": "Tipue is a small web development studio based in North London. We've been around for well over a decade. We design innovative add-ins, plugins, code and features with heavy-duty Perl, MySQL and jQuery.", "tags": "", "url": "http://www.tipue.com/about"}, {"title": "The Tipue blog - The complete guide to centering a div", "text": "Every new developer inevitably finds that centering a div isn't as obvious as you'd expect. Centering what's inside a div is easy enough by giving the text-align property a value of center, but then things tend to get a bit sticky. When you get to centering a div vertically, you can end up in a world of CSS hurt.", "tags": "HTML", "url": "http://www.tipue.com/blog/center-a-div"}, {"title": "The Tipue blog - Native HTML5 autocomplete with input list", "text": "This article shows how with the HTML5 input list attribute and datalist element you can easily set up an input box with a custom autocomplete without jQuery, JavaScript or similar.", "tags": "", "url": "http://www.tipue.com/blog/input-list"}, {"title": "The Tipue blog - The really simple guide to z-index", "text": "The CSS z-index property often trips up new and even experienced developers. The aim of this article is to boil down a somewhat-complex specification to 3 major points, which should ease most z-index pain.", "tags": "", "url": "http://www.tipue.com/z-index"} ]}; ================================================ FILE: doc/tipuesearch/tipuesearch_set.js ================================================ /* Tipue Search 5.0 Copyright (c) 2015 Tipue Tipue Search is released under the MIT License http://www.tipue.com/search */ /* Stop words Stop words list from http://www.ranks.nl/stopwords */ var tipuesearch_stop_words = ["a", "about", "above", "after", "again", "against", "all", "am", "an", "and", "any", "are", "aren't", "as", "at", "be", "because", "been", "before", "being", "below", "between", "both", "but", "by", "can't", "cannot", "could", "couldn't", "did", "didn't", "do", "does", "doesn't", "doing", "don't", "down", "during", "each", "few", "for", "from", "further", "had", "hadn't", "has", "hasn't", "have", "haven't", "having", "he", "he'd", "he'll", "he's", "her", "here", "here's", "hers", "herself", "him", "himself", "his", "how", "how's", "i", "i'd", "i'll", "i'm", "i've", "if", "in", "into", "is", "isn't", "it", "it's", "its", "itself", "let's", "me", "more", "most", "mustn't", "my", "myself", "no", "nor", "not", "of", "off", "on", "once", "only", "or", "other", "ought", "our", "ours", "ourselves", "out", "over", "own", "same", "shan't", "she", "she'd", "she'll", "she's", "should", "shouldn't", "so", "some", "such", "than", "that", "that's", "the", "their", "theirs", "them", "themselves", "then", "there", "there's", "these", "they", "they'd", "they'll", "they're", "they've", "this", "those", "through", "to", "too", "under", "until", "up", "very", "was", "wasn't", "we", "we'd", "we'll", "we're", "we've", "were", "weren't", "what", "what's", "when", "when's", "where", "where's", "which", "while", "who", "who's", "whom", "why", "why's", "with", "won't", "would", "wouldn't", "you", "you'd", "you'll", "you're", "you've", "your", "yours", "yourself", "yourselves"]; // Word replace var tipuesearch_replace = {'words': [ {'word': 'tipua', 'replace_with': 'tipue'}, {'word': 'javscript', 'replace_with': 'javascript'}, {'word': 'jqeury', 'replace_with': 'jquery'} ]}; // Weighting var tipuesearch_weight = {'weight': [ {'url': 'http://www.tipue.com', 'score': 200}, {'url': 'http://www.tipue.com/search', 'score': 100}, {'url': 'http://www.tipue.com/about', 'score': 100} ]}; // Stemming var tipuesearch_stem = {'words': [ {'word': 'e-mail', 'stem': 'email'}, {'word': 'javascript', 'stem': 'jquery'}, {'word': 'javascript', 'stem': 'js'} ]}; // Internal strings var tipuesearch_string_1 = 'No title'; var tipuesearch_string_2 = 'Showing results for'; var tipuesearch_string_3 = 'Search instead for'; var tipuesearch_string_4 = '1 result'; var tipuesearch_string_5 = 'results'; var tipuesearch_string_6 = 'Prev'; var tipuesearch_string_7 = 'Next'; var tipuesearch_string_8 = 'Nothing found'; var tipuesearch_string_9 = 'Common words are largely ignored'; var tipuesearch_string_10 = 'Search too short'; var tipuesearch_string_11 = 'Should be one character or more'; var tipuesearch_string_12 = 'Should be'; var tipuesearch_string_13 = 'characters or more'; ================================================ FILE: setup.py ================================================ from setuptools import setup requires = ['jinja2 >= 2.10', 'pygments', 'markdown >= 3.0','pyyaml', 'beautifulsoup4'] entry_points = { 'console_scripts': [ 'urubu = urubu.main:main', ] } setup( name="urubu", version="1.4.1", url='http://urubu.jandecaluwe.com', author='Jan Decaluwe', author_email='jan@jandecaluwe.com', description="A micro CMS for static websites with a focus " "on good navigation practices.", packages=['urubu'], include_package_data=True, install_requires=requires, entry_points=entry_points, extras_require={ 'test': ['pytest', 'sh'], }, classifiers=[ 'Development Status :: 3 - Alpha', 'License :: OSI Approved :: GNU Affero General Public License v3', 'Operating System :: OS Independent', 'Programming Language :: Python :: 2.7', 'Topic :: Internet :: WWW/HTTP', 'Topic :: Software Development :: Libraries :: Python Modules', ], ) ================================================ FILE: tox.ini ================================================ [tox] envlist = py310 [testenv] changedir=urubu/tests deps= markdown >= 3.0 pytest sh beautifulsoup4 pygments commands= py.test --basetemp={envtmpdir} {posargs} --ignore=test_doc.py py.test --basetemp={envtmpdir} {posargs} test_doc.py ================================================ FILE: urubu/__init__.py ================================================ # Copyright 2014-2024 Jan Decaluwe # # This file is part of Urubu. # # Urubu is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Urubu 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 Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with Urubu. If not, see . __version__ = "1.4.1" from warnings import warn class UrubuWarning(UserWarning): pass def urubu_warn(kind, msg='', fn=''): if fn: fn = 'in ' + fn + ': ' if msg: msg = ': ' + "'{}'".format(msg) warn(fn + kind + msg, UrubuWarning, stacklevel=2) class UrubuError(Exception): def __init__(self, kind, msg='', fn=''): self.kind = kind self.msg = msg self.fn = fn def __str__(self): fn = self.fn if fn: fn = 'in ' + fn + ': ' msg = self.msg if msg: msg = ': ' + "'{}'".format(msg) return fn + self.kind + msg class _error(): pass class _warning(): pass _warning.no_yamlfm = "No yaml front matter - ignored" _warning.undef_tag_layout = "Tags defined, but no tag layout found" _warning.undef_ref_md = 'Undefined reference' _warning.undef_anchor = "Undefined anchor" _error.ambig_refid = "Ambiguous reference id" _error.undef_ref = "Undefined reference" _error.ambig_ref = "Ambiguous reference, cannot resolve" _error.undef_info = "Missing attribute" _error.date_format = "Date format error - should be YYYY-MM-DD" _error.undef_key = "Undefined key" _error.undef_content = "No 'content' or 'order' specified" _error.undef_reflink_key = "Undefined key in site reflink" _error.ambig_ref_md = 'Ambiguous reference' _error.no_index = 'Missing index file' ================================================ FILE: urubu/__main__.py ================================================ # Copyright 2014 Jan Decaluwe # # This file is part of Urubu. # # Urubu is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Urubu 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 Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with Urubu. If not, see . from urubu import main main.main() ================================================ FILE: urubu/config.py ================================================ # Copyright 2014 Jan Decaluwe # # This file is part of Urubu. # # Urubu is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Urubu 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 Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with Urubu. If not, see . import os siteinfofn = '_site.yml' sitedir = '_build' tagdir = 'tag' tagid = '/' + tagdir tagindexid = tagid + '/' + 'index' tag_layout = 'tag' layoutdir = '_layouts' tipuesearchdir = 'tipuesearch' tipuesearch_content = 'tipuesearch_content.json' ================================================ FILE: urubu/httphandler.py ================================================ # Copyright 2015 Sreepathi Pai # # This file is part of Urubu. # # Urubu is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Urubu 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 Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with Urubu. If not, see . import http.server as httpserver class AliasingHTTPRequestHandler(httpserver.SimpleHTTPRequestHandler): def do_GET(self): baseurl = self.server.baseurl if not baseurl: httpserver.SimpleHTTPRequestHandler.do_GET(self) return wk_baseurl = "/%s/" % (baseurl) if self.path == wk_baseurl[:-1]: # handle /$baseurl -> /$baseurl/ self.send_response(301, 'Moved Permanently') self.send_header('Location', wk_baseurl) self.end_headers() return if self.path[:len(wk_baseurl)] == wk_baseurl: # translate /$baseurl/path internally to /path and serve self.path = self.path[len(wk_baseurl)-1:] httpserver.SimpleHTTPRequestHandler.do_GET(self) return else: # handle /xyz/path -> /$baseurl/xyz/path # # usually caused by underlying server sending a redirect # to non-baseurl-prefixed path self.send_response(302, 'Moved Temporarily') sep = "/" if self.path[0] != "/" else "" # note this replicates underlying bugs in that Location is # not absolute as required by the spec and we throw away # '?' and '#' self.send_header('Location', "/%s%s%s" % (baseurl, sep, self.path)) self.end_headers() return ================================================ FILE: urubu/main.py ================================================ # Copyright 2014 Jan Decaluwe # # This file is part of Urubu. # # Urubu is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Urubu 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 Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with Urubu. If not, see . import argparse import os from sys import stderr from urubu import __version__ from urubu import project import socketserver import http.server as httpserver from urubu.httphandler import AliasingHTTPRequestHandler __IDESC__ = """ Micro CMS tool to build and test static websites. """ __IEPILOG__ = """ Documentation: """ def serve(baseurl, host='localhost', port=8000): """HTTP server straight from the docs.""" # allow running this from the top level if os.path.isdir('_build'): os.chdir('_build') # local use, address reuse should be OK socketserver.TCPServer.allow_reuse_address = True handler = AliasingHTTPRequestHandler httpd = socketserver.TCPServer((host, port), handler) httpd.baseurl = baseurl if host == '': print("This web server is not safe for public/production use.", file=stderr) print("Serving all peers at port {port}...\n\ Browse (*:{port})".format(host=host, port=port)) else: print("Serving {host} at port {port}...\n\ Browse .".format(host=host, port=port)) if httpd.baseurl: print("Using baseurl {}".format(httpd.baseurl)) httpd.serve_forever() def main(): parser = argparse.ArgumentParser(prog='python -m urubu', add_help=False, epilog=__IEPILOG__, description=__IDESC__) parser.add_argument('-h', '--help', action='help', help="show program's help and exit") parser.add_argument('-v', '--version', action='version', version=__version__) parser.add_argument('command', choices=['build', 'serve', 'serveany']) args = parser.parse_args() if args.command == 'build': project.build() elif args.command == 'serve': proj = project.load() serve(proj.site['baseurl']) elif args.command == 'serveany': proj = project.load() serve(proj.site['baseurl'], host='') ================================================ FILE: urubu/md_extensions.py ================================================ # Copyright 2014-2015 Jan Decaluwe # # This file is part of Urubu. # # Urubu is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Urubu 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 Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with Urubu. If not, see . import posixpath import re import markdown import logging logging.captureWarnings(False) from markdown import Extension from markdown.extensions import toc from markdown.treeprocessors import Treeprocessor from markdown.inlinepatterns import ReferenceInlineProcessor, REFERENCE_RE from markdown.inlinepatterns import AsteriskProcessor, EmStrongItem from markdown.inlinepatterns import EM_STRONG2_RE, STRONG_EM2_RE from markdown.inlinepatterns import SMART_STRONG_EM_RE, SMART_STRONG_RE, SMART_EMPHASIS_RE from urubu import UrubuWarning, urubu_warn, UrubuError, _warning, _error def _set_dl_class(tree): for item in tree: if item.tag == 'dl': item.set('class', 'dl-horizontal') _set_dl_class(item) class DLClass(Treeprocessor): def run(self, root): _set_dl_class(root) return None class DLClassExtension(Extension): """Add 'dl-horizontal' class to definition list elements (for bootstrap).""" def extendMarkdown(self, md): md.treeprocessors.register(DLClass(md), 'dlclass', 3) def _set_table_class(tree): for item in tree: if item.tag == 'table': item.set('class', 'table') _set_table_class(item) class TableClass(Treeprocessor): def run(self, root): _set_table_class(root) return None class TableClassExtension(Extension): """Add 'table' class to table elements (for bootstrap).""" def extendMarkdown(self, md): md.treeprocessors.register(TableClass(md), 'tableclass', 4) class ProjectReferenceInlineProcessor(ReferenceInlineProcessor): def handleMatch(self, m, data): text, index, handled = self.getText(data, m.end(0)) if not handled: return None, None, None ref, end, shortref, handled = self.evalRef(data, index, text) if not handled: return None, None, None # Clean up linebreaks in ref ref = self.NEWLINE_CLEANUP_RE.sub(' ', ref) id = ref.lower() if id in self.md.references: href, title = self.md.references[id] else: anchor = None if '#' in ref: ref, anchor = ref.split('#', 1) this = self.md.this if not posixpath.isabs(ref): # treat empty ref as reference to current page if not ref: ref = this['components'][-1] rootrelpath = '/' + '/'.join(this['components'][:-1]) id = posixpath.normpath(posixpath.join(rootrelpath, ref)) id = id.lower() else: id = ref.lower() ref = ref.lower() if ref in self.md.site['reflinks']: if (ref != id) and (id in self.md.site['reflinks']): raise UrubuError(_error.ambig_ref_md, msg=ref, fn=this['fn']) id = ref if id in self.md.site['reflinks']: item = self.md.site['reflinks'][id] href, title = item['url'], item['title'] if shortref: text = title if anchor is not None: text = anchor if anchor is not None: anchor = toc.slugify(anchor, '-') href = '%s#%s' % (href, anchor) anchorref = '%s#%s' % (id, anchor) self.md.this['_anchorrefs'].add(anchorref) else: # ignore undefined refs urubu_warn(_warning.undef_ref_md, msg=ref, fn=this['fn']) return None, None, None return self.makeTag(href, title, text), m.start(0), end def evalRef(self, data, index, text): """ Evaluate ref from [text][ref] or [ref][] """ shortref = False m = self.RE_LINK.match(data, pos=index) if not m: return None, index, shortref, False else: ref = m.group(1) end = m.end(0) if not ref: ref = text return ref, end, shortref, True class ProjectShortReferenceInlineProcessor(ProjectReferenceInlineProcessor): def evalRef(self, data, index, text): """ Evaluate ref from [text] """ shortref = True return text, index, shortref, True class ProjectReferenceExtension(Extension): """Overwrite reference patterns with project reference extensions.""" def extendMarkdown(self, md): md.inlinePatterns.deregister('reference') md.inlinePatterns.register(ProjectReferenceInlineProcessor(REFERENCE_RE, md), 'reference', 170) md.inlinePatterns.deregister('short_reference') md.inlinePatterns.register(ProjectShortReferenceInlineProcessor(REFERENCE_RE, md), 'short_reference', 130) class ExtractAnchorsClass(Treeprocessor): def run(self, tree): this = self.md.this thisid = this['id'] components = this['components'] for item in tree: if 'id' in item.attrib: self.md.anchors.add("%s#%s" % (thisid, item.attrib['id'])) # add special version for index files if components[-1] == 'index': navid = thisid[:-6] # remove trailing backslash also self.md.anchors.add("%s#%s" % (navid, item.attrib['id'])) return None class ExtractAnchorsExtension(Extension): def extendMarkdown(self, md): md.treeprocessors.register(ExtractAnchorsClass(md), 'extractanchors', 5) # extension for the tag class UnderscoreMarkProcessor(AsteriskProcessor): """Emphasis processor for handling strong and mark matches inside underscores.""" PATTERNS = [ EmStrongItem(re.compile(EM_STRONG2_RE, re.DOTALL | re.UNICODE), 'double', 'strong,mark'), EmStrongItem(re.compile(STRONG_EM2_RE, re.DOTALL | re.UNICODE), 'double', 'mark,strong'), EmStrongItem(re.compile(SMART_STRONG_EM_RE, re.DOTALL | re.UNICODE), 'double2', 'strong,mark'), EmStrongItem(re.compile(SMART_STRONG_RE, re.DOTALL | re.UNICODE), 'single', 'strong'), EmStrongItem(re.compile(SMART_EMPHASIS_RE, re.DOTALL | re.UNICODE), 'single', 'mark') ] class MarkTagExtension(Extension): def extendMarkdown(self, md): md.inlinePatterns.deregister('em_strong2') md.inlinePatterns.register(UnderscoreMarkProcessor(r'_'), 'em_strong2', 50) ================================================ FILE: urubu/processors.py ================================================ # Copyright 2014 Jan Decaluwe # # This file is part of Urubu. # # Urubu is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Urubu 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 Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with Urubu. If not, see . import os, sys, json, itertools import markdown import logging logging.captureWarnings(False) from bs4 import BeautifulSoup import jinja2 from urubu import UrubuWarning, UrubuError, urubu_warn, _warning from urubu import md_extensions from urubu.config import layoutdir, tag_layout, tipuesearchdir, tipuesearch_content def skip_yamlfm(f): """Return source of a file without yaml frontmatter.""" f.readline() found = False lines = [] for line in f.readlines(): if found: lines.append(line) if line.strip() == '---': found = True return ''.join(lines) class ContentProcessor(object): def __init__(self, sitedir, project): self.sitedir = sitedir self.filelist = project.filelist self.navlist = project.navlist self.taglist = project.taglist self.site = project.site dlclass = md_extensions.DLClassExtension() tableclass = md_extensions.TableClassExtension() projectref = md_extensions.ProjectReferenceExtension() extractanchors = md_extensions.ExtractAnchorsExtension() marktag = md_extensions.MarkTagExtension() # there is a strange interaction between smarty and reference links that start on a new line # disabling smarty for now... # extensions = ['extra', 'codehilite', 'headerid', 'toc', 'smarty', tableclass, projectref] extensions = ['markdown.extensions.extra', 'markdown.extensions.codehilite', 'markdown.extensions.toc', dlclass, tableclass, projectref, extractanchors] if self.site['mark_tag_support']: extensions.append(marktag) extension_configs = {'markdown.extensions.codehilite': [('guess_lang', 'False'), ('linenums', 'False')], 'markdown.extensions.toc': [('baselevel', 2)] } self.md = markdown.Markdown(extensions=extensions, extension_configs=extension_configs) self.md.site = self.site self.md.anchors = project.anchors if 'strict_undefined' in self.site and self.site['strict_undefined']: undefined_class = jinja2.StrictUndefined else: undefined_class = jinja2.Undefined env = self.env = jinja2.Environment( loader=jinja2.FileSystemLoader(layoutdir), lstrip_blocks=True, trim_blocks=True, undefined=undefined_class) env.filters.update(project.filters) self.templates = {} for layout in project.layouts: self.templates[layout] = self.env.get_template(layout + '.html') # layout for tags is optional, triggers index file generation per tag try: self.templates[tag_layout] = self.env.get_template( tag_layout + '.html') except jinja2.exceptions.TemplateNotFound: if self.taglist: urubu_warn(_warning.undef_tag_layout, msg=tag_layout) def process(self): """Process the content. Conversion and rendering are done in separate phases, so that the full content is available to the rendering process. """ self.convert() self.alt_layouts() self.pagination() self.render() self.make_tipuesearch_content() def alt_layouts(self): # If a file contains the alt_layouts attribute, then # we need to generate a copy of the file for each # additional layout, in the location given. Each # alt layout has two fields, layout and location for info in self.filelist: if 'alt_layouts' in info: for layout in info['alt_layouts']: new_info = info.copy() # Make sure the alt layout is available if layout['layout'] not in self.templates: self.templates[layout['layout']] = self.env.get_template(layout['layout'] + '.html') # Set the layout of the new file new_info['layout'] = layout['layout'] # Set path of the new file import ntpath filename = ntpath.basename(new_info['fn']) new_info['fn'] = layout['location']+"\\"+filename # Prevent the new file from generating more new files del new_info['alt_layouts'] self.filelist.append(new_info) def pagination(self): # We look at attributes in pages here, e.g.: # # items_per_page: 5 # items_index: news\index.md # # OR # # items_per_page: 5 # items_filter: mysteries time-loop # # We then find the info item for the items index/filter and # use it to create more entries for the current item in # the file list, splitting it out into items_per_page # chunks for each file. # # The filters are the same ones defined in _python for Jinja2 # to use. The name of the function is followed by its parameters # # The page and any new pages created from it will get new attributes: # # numpages - the number of total pages generated # thispage - the page number of this page in the chain # prevpage - the previous page in the chain # nextpage - the next page in the chain # pages - a list of page numbers and page objects # # The first page will have no prevpage, and the last page # will have no nextpage. import math for info in self.filelist: source = None if 'items_per_page' in info: if 'items_index' in info: if info['items_index'] == "this": source = info['content'] else: source = next(x for x in self.filelist if x['fn'] == info['items_index'])['content'] if 'items_filter' in info: filter = info['items_filter'].split() source = self.env.filters[filter[0]](*filter[1:]) if source: items_per_page = info['items_per_page'] # This will be a shared list among all the pages # that lists each page along with its page number, # e.g. {'pagenum': 1, 'page': info} pages = [] # Split source into items_per_page sized chunks, # starting with info and then creating new # files with incrementing numbers chunks = math.ceil(len(source) / items_per_page) # First chunk is always the current page info['content'] = source[0:items_per_page] # See if we even need to worry about pagination # Maybe everything fits on the one page already if len(source) <= items_per_page: continue info['numpages'] = chunks info['thispage'] = 1 info['pages'] = pages pages.append({'pagenum': 1, 'page': info}) chunk = 1 prev_page = info # If we need more chunks, split off new pages for them while chunk < chunks: chunk += 1 new_info = info.copy() # Prevent the new page from spinning off new pages del new_info['items_per_page'] new_info['pages'] = pages pages.append({'pagenum': chunk, 'page': new_info}) # Set the content to the right slice of the source new_info['content'] = source[(chunk-1)*items_per_page:(chunk-1)*items_per_page+items_per_page] new_info['numpages'] = chunks new_info['thispage'] = chunk # Name the new page based on its chunk number fn_parts = os.path.splitext(new_info['fn']) new_info['fn'] = fn_parts[0]+str(chunk)+fn_parts[1] fn_parts = os.path.splitext(new_info['url']) new_info['url'] = fn_parts[0]+str(chunk)+fn_parts[1] # Setup the prevpage and nextpage attributes new_info['prevpage'] = prev_page prev_page['nextpage'] = new_info # We may have inherited this from the first chunk if 'nextpage' in new_info: del new_info['nextpage'] prev_page = new_info self.filelist.append(new_info) def convert(self): for info in self.filelist: fn = info['fn'] with open(fn, encoding='utf-8-sig') as inf: src = skip_yamlfm(inf) self.md.this = info # first process as a template try: templ = self.env.from_string(src) src = templ.render(this=info, site=self.site) except: exc, msg, tb = sys.exc_info() raise UrubuError(str(exc), msg=msg, fn=fn) self.md.toc = '' info['body'] = self.md.convert(src) info['toc'] = '' if hasattr(self.md, 'toc'): # filter out empty tocs, 35 is the magic length if len(self.md.toc) > 35: info['toc'] = self.md.toc # markdown support in keys mdkeys = [key for key in info if key[-3:] == '.md'] for mdkey in mdkeys: key = mdkey[:-3] info[key] = self.md.convert(info[mdkey]) self.md.reset() for info in self.navlist: # markdown support in keys mdkeys = [key for key in info if key[-3:] == '.md'] for mdkey in mdkeys: key = mdkey[:-3] info[key] = self.md.convert(info[mdkey]) self.md.reset() def render(self): # content files for info in self.filelist: if info['layout'] is None: continue self.render_file(info) # tag index files if tag_layout not in self.templates: return for info in self.taglist: self.render_file(info) def render_file(self, info): layout = info['layout'] templ = self.templates[layout] html = templ.render(this=info, site=self.site) # extract text from html for search support self.extract_text(html, info) fn = info['fn'] # check if filename is overriden if info.get('saveas') is not None: outfn = os.path.join(self.sitedir, info.get('saveas')) else: bfn, ext = os.path.splitext(fn) outfn = os.path.join(self.sitedir, bfn) + self.site['file_ext'] with open(outfn, 'w', encoding='utf-8', errors='strict') as outf: outf.write(html) def extract_text(self, html, info): # select main tag for search content m = BeautifulSoup(html, "html.parser").select('main') text = "" if m: text = m[0].get_text(" ", strip=True) info['text'] = text def make_tipuesearch_content(self): tsd = os.path.join(self.sitedir, tipuesearchdir) if not os.path.isdir(tsd): return tsc = os.path.join(tsd, tipuesearch_content) items = [] # use tag index files if they have been rendered taglist = [] if tag_layout in self.templates: taglist = self.taglist for info in itertools.chain(self.filelist, taglist): if 'text' not in info: continue tags = "" if 'tags' in info: tags = ' '.join(info['tags']) item = {'text' : info['text'], 'title': info['title'], 'url' : info['url'], 'tags' : tags} items.append(item) if len(items) <= 0: return obj = {'pages': items} with open(tsc, 'w', encoding='utf-8') as fd: # json.dump is buggy in Python2 -- use workaround # print json.dumps(obj, ensure_ascii=False, indent=4) data = json.dumps(obj, ensure_ascii=False, indent=4, sort_keys=True) fd.write(str(data)) ================================================ FILE: urubu/project.py ================================================ # Copyright 2014, 2015 Jan Decaluwe # # This file is part of Urubu. # # Urubu is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Urubu 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 Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with Urubu. If not, see . import os, sys import yaml import fnmatch import shutil import datetime import itertools import importlib from operator import itemgetter from urubu import UrubuWarning, UrubuError, urubu_warn, _warning, _error from urubu import readers, processors from urubu.config import (siteinfofn, sitedir, tagdir, tagid, tagindexid, tag_layout) def require_key(key, mapping, tipe, fn): type_error = "{}: '{}' value should be of type {}" if key in mapping: if not (isinstance(mapping[key], tipe)): raise TypeError(type_error.format(fn, key, tipe)) def get_relpath(path, start): return os.path.relpath(path, start) def get_components(path, hasext=True): p = path if hasext: p, ext = os.path.splitext(path) p = p.lstrip(os.curdir) p = p.strip(os.sep) components = [] if p: components = p.split(os.sep) return components def make_id(components, lowercased=True): id = ('/' + '/'.join(components)) if lowercased: return id.lower() return id def make_clean(dir): for fn in os.listdir(dir): p = os.path.join(dir, fn) if os.path.isdir(p) and not fn == '.git': shutil.rmtree(p) elif os.path.isfile(p) and not fn == 'CNAME': os.remove(p) class Project(object): def __init__(self): self.cwd = os.getcwd() self.site = {'baseurl': None, 'reflinks': {}, 'link_ext': '.html', 'file_ext': '.html', 'mark_tag_support': True } self.sitedir = sitedir self.get_siteinfo() """Get user-defined python hooks.""" # load _python module from cwd try: _python = importlib.import_module('_python') except ModuleNotFoundError: _python = None self.filters = getattr(_python, 'filters', {}) self.validators = getattr(_python, 'validators', {}) # overwrite placeholder method if function found self.process_info = getattr(_python, 'process_info', self.process_info) self.filelist = [] self.navlist = [] self.taglist = [] self.tagmap = {} self.layouts = [] # anchors to be filled in by markdown processor self.anchors = set() def process_info(self, info, site): """Plugin placeholder""" pass def get_siteinfo(self): """Get the siteinfo from the yaml data file.""" if not os.path.isfile(siteinfofn): return with open(siteinfofn, encoding='utf-8-sig') as f: meta = yaml.safe_load(f) # validate the site reflinks and add them if 'reflinks' in meta: for id in meta['reflinks']: info = meta['reflinks'][id] self.validate_sitereflink(id, info) self.add_reflink(id, info) del meta['reflinks'] self.site.update(meta) # check for custom build directory if 'build_dir' in meta: builddir = os.path.expanduser(meta['build_dir']) self.sitedir = os.path.abspath(builddir) def validate_sitereflink(self, id, info): if 'title' not in info: raise UrubuError(_error.undef_reflink_key, fn=id, msg=id + ': title') if 'url' not in info: raise UrubuError(_error.undef_reflink_key, fn='_site.yml', msg=id + ': url') def add_reflink(self, id, info): """Add a valid reflink to the site reflinks.""" id = id.lower() if id in self.site['reflinks']: cFile = self.site['reflinks'][id] errmsg = "id '{ID}' in {FN} conflicts with {CFN}".\ format(ID=id, FN=info['fn'], CFN=cFile['fn']) raise UrubuError(_error.ambig_refid, msg=errmsg) self.site['reflinks'][id] = info def finalize_local_url(self, url): """Add a base to a local URL, if configured.""" if self.site['baseurl']: url = '/' + self.site['baseurl'] + url return url def get_contentinfo(self): """Get info from the markdown content files.""" pattern = '*.md' ignore_patterns = self.get_ignore_patterns() for path, dirnames, filenames in os.walk(self.cwd): relpath = get_relpath(path, self.cwd) if any(fnmatch.fnmatch(relpath, ip) for ip in ignore_patterns): continue content_found = index_found = False for fn in filenames: if fnmatch.fnmatch(fn, pattern): # normalize to convert ./foo into foo # to avoid problems with ignore_patterns matching relfn = os.path.normpath(os.path.join(relpath, fn)) if any(fnmatch.fnmatch(relfn, ip) for ip in ignore_patterns): continue meta = readers.get_yamlfm(relfn) if meta is None: urubu_warn(_warning.no_yamlfm, fn=relfn) continue fileinfo = self.make_fileinfo(relfn, meta) self.filelist.append(fileinfo) self.process_info(fileinfo, self.site) # validate after file info has been added so it can be used self.validate_fileinfo(fileinfo) self.add_reflink(fileinfo['id'], fileinfo) if fn == 'index.md': index_found = True # start from fileinfo of index file navinfo = self.make_navinfo(relpath, fileinfo) self.navlist.append(navinfo) self.validate_navinfo(navinfo) self.add_reflink(navinfo['id'], navinfo) # add nav info to tag map self.add_info_to_tagmap(navinfo) else: content_found = True # add id for non-index files to tag tags self.add_info_to_tagmap(fileinfo) # a folder with content but no index is an error if content_found and not index_found: raise UrubuError(_error.no_index, msg='', fn=relpath) def validate_fileinfo(self, info): fn = info['fn'] # layout is mandatory if 'layout' not in info: raise UrubuError(_error.undef_info, msg='layout', fn=fn) if info['layout'] is None: return layout = info['layout'] # modification date, always available t = os.path.getmtime(fn) info['mdate'] = datetime.date.fromtimestamp(t) # first run a validator if it exist if layout in self.validators: self.validators[layout](info) # a validator may add/modify attributes layout = info['layout'] if layout is None: return if layout not in self.layouts: self.layouts.append(layout) # title if 'title' not in info: raise UrubuError(_error.undef_info, msg='title', fn=fn) # Support integer titles by converting to string # this matters for the json dump for search # test type explicitly to avoid problems with unicode titles... if isinstance(info['title'], int): info['title'] = str(info['title']) # date if 'date' in info: if not isinstance(info['date'], datetime.date): raise UrubuError(_error.date_format, fn=fn) # tags if 'tags' in info: # TODO: make sure it's a list of strings if isinstance(info['tags'], str): info['tags'] = [info['tags']] # TODO: normalize tags def validate_navinfo(self, info): fn = info['indexfn'] if ('content' not in info) and ('order' not in info): # exception: tag folder doesn't require content atribute # set it to empty list align with normal folders if info['id'] == tagid: info['content'] = [] else: raise UrubuError(_error.undef_content, fn=fn) require_key('content', info, list, fn) def make_fileinfo(self, relfn, meta): """Make a fileinfo dict.""" info = {} info['fn'] = relfn info['components'] = components = get_components( relfn if meta.get('saveas') is None else meta.get('saveas')) info['id'] = make_id(components) # make html url from ref info['url'] = self.finalize_local_url( make_id(components, lowercased=False) + self.site['link_ext']) info['_anchorrefs'] = set() info.update(meta) return info def make_navinfo(self, relpath, fileinfo): """Make a navinfo dict.""" # start from fileinfo of index file info = fileinfo.copy() # overwrite attributes according to navinfo view info['indexfn'] = info['fn'] info['fn'] = relpath info['components'] = components = get_components(relpath) info['id'] = make_id(components) # add trailing slash for navigation url info['url'] = self.finalize_local_url(info['id']) if info['url'] != '/': info['url'] += '/' return info def add_info_to_tagmap(self, info): """Add id to tagmap.""" # tags are optional if 'tags' not in info: return for tag in info['tags']: if tag not in self.tagmap: self.tagmap[tag] = [] self.tagmap[tag].append(info) def resolve_reflinks(self): for info in self.navlist: if 'content' in info: self.resolve_content(info) else: # order assert 'order' in info self.get_content(info) # make reflinks content available in index file also index_id = make_id(info['components'] + ['index']) self.site['reflinks'][index_id]['content'] = info['content'] def resolve_content(self, info): """Resolve reflinks in a folder.""" refcontent = [] for item in info['content']: if isinstance(item, dict): link = self.resolve_linkspec(item, info) else: link = self.resolve_ref(item, info) refcontent.append(link) # overwrite content ids with resolved refs info['content'] = refcontent def resolve_ref(self, ref, info): """Resolve a reference.""" reflinks = self.site['reflinks'] ref = ref.lower() path = os.path.normpath(os.path.join(info['fn'], ref)) indexfn = info['indexfn'] id = make_id(get_components(path, hasext=False)) if ref in reflinks: if (ref != id) and (id in reflinks): raise UrubuError(_error.ambig_ref, msg=ref, fn=indexfn) id = ref elif not id in reflinks: raise UrubuError(_error.undef_ref, msg=ref, fn=indexfn) return reflinks[id] def resolve_linkspec(self, linkspec, info): link = {} link['url'] = link['title'] = linkspec.get('url', None) if 'ref' in linkspec: reflink = self.resolve_ref(linkspec['ref'], info) link.update(reflink) if 'title' in linkspec: link['title'] = linkspec['title'] return link def get_content(self, info): """Infer sorted content of a folder.""" reflinks = self.site['reflinks'] refcontent = [] key = info['order'] reverse = info.get('reverse', False) navcomps = info['components'] def pred(item): itemcomps = item['components'] if len(itemcomps) == len(navcomps) + 1 and \ itemcomps[:-1] == navcomps and \ itemcomps[-1] != 'index' and \ item['layout'] is not None: if key not in item: raise UrubuError(_error.undef_key, msg=key, fn=item['fn']) return True return False allinfo = itertools.chain(self.filelist, self.navlist) refcontent = filter(pred, allinfo) def get_keyval(item): return item[key] refcontent = sorted(refcontent, key=get_keyval, reverse=reverse) info['content'] = refcontent def make_breadcrumbs(self): for info in self.filelist: breadcrumbs = [] id = '' comps = info['components'] # discard index if comps[-1] == 'index': comps = comps[:-1] for comp in comps: id = id + '/' + comp id = id.lower() breadcrumbs.append(self.site['reflinks'][id]) info['breadcrumbs'] = breadcrumbs def make_pager(self): for info in self.navlist: content = info['content'] if not content: continue content[0]['prev'] = None for i in range(1, len(content)): content[i - 1]['next'] = content[i] content[i]['prev'] = content[i - 1] content[-1]['next'] = None def make_taginfo(self, tag, content): """Make a taginfo dict.""" info = {} info['title'] = info['tag'] = tag info['layout'] = tag_layout info['fn'] = os.path.join(tagdir, tag, 'index') info['components'] = components = (tagdir, tag) info['id'] = make_id(components, lowercased=False) # add trailing slash for tag index url info['url'] = self.finalize_local_url(info['id']) + '/' info['content'] = content return info def process_tags(self): """ Process tag map and tag content.""" def get_date(item): """ Return item's date, or mdate as fallback.""" if 'date' in item: return item['date'] else: return item['mdate'] for tag in self.tagmap.keys(): # sort tag content by date content = sorted(self.tagmap[tag], key=get_date, reverse=True) taginfo = self.make_taginfo(tag, content) self.taglist.append(taginfo) self.add_reflink(taginfo['id'], taginfo) # sort tags according to content length, then alphabetically # to get sort order right, invert content length def get_tagkey(taginfo): return (-len(taginfo['content']), taginfo['tag']) self.taglist = sorted(self.taglist, key=get_tagkey) # set up tagid info dict if it doesn't exist already if tagid not in self.site['reflinks']: self.site['reflinks'][tagid] = {} self.site['reflinks'][tagid]['content'] = self.taglist # propagate content to index file if it exists if tagindexid in self.site['reflinks']: self.site['reflinks'][tagindexid]['content'] = self.taglist def get_ignore_patterns(self): ignore_patterns = ('.?*', '_*', 'Makefile') if 'ignore_patterns' in self.site: ignore_patterns += tuple(self.site['ignore_patterns']) return ignore_patterns def get_keep_files(self): if 'keep_files' in self.site: return self.site['keep_files'] return [] def check_anchor_links(self): for info in self.filelist: for ar in info['_anchorrefs']: if not ar in self.anchors: urubu_warn(_warning.undef_anchor, msg=ar, fn=info['id'] ) def make_site(self): """Make the site.""" # Keep sitedir alive if it exists, for the server if not os.path.exists(self.sitedir): os.mkdir(self.sitedir) make_clean(self.sitedir) ignore_patterns = self.get_ignore_patterns() + ('*.md',) ignore = shutil.ignore_patterns(*ignore_patterns) for fn in os.listdir(self.cwd): if any(fnmatch.fnmatch(fn, ip) for ip in ignore_patterns): continue wp = os.path.join(self.cwd, fn) sp = os.path.join(self.sitedir, fn) if os.path.isdir(wp): shutil.copytree(wp, sp, ignore=ignore) elif os.path.isfile(wp): shutil.copyfile(wp, sp) # explicit files to keep for fn in self.get_keep_files(): wp = os.path.join(self.cwd, fn) sp = os.path.join(self.sitedir, fn) if os.path.isfile(wp): shutil.copyfile(wp, sp) # make tag index dirs if self.taglist: tagpath = os.path.join(self.sitedir, tagdir) if not os.path.isdir(tagpath): os.mkdir(tagpath) for taginfo in self.taglist: os.mkdir(os.path.join(tagpath, taginfo['tag'])) self.process_content() self.check_anchor_links() def process_content(self): """Process the content files.""" p = processors.ContentProcessor(self.sitedir, project=self) p.process() def load(): proj = Project() return proj def build(): proj = load() proj.get_contentinfo() proj.resolve_reflinks() proj.make_breadcrumbs() proj.make_pager() proj.process_tags() proj.make_site() ================================================ FILE: urubu/readers.py ================================================ # Copyright 2014 Jan Decaluwe # # This file is part of Urubu. # # Urubu is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Urubu 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 Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with Urubu. If not, see . import yaml import re def get_yamlfm(fn): """Return the yaml frontmatter.""" info = _get_yamlfm_helper(fn) return info def _get_yamlfm_helper(fn): with open(fn, 'r', encoding='utf-8-sig') as f: line = f.readline() if line.strip() != '---': return None lines = [] while True: line = f.readline() if not line: return None elif line.strip() == '---': s = ''.join(lines) meta = yaml.safe_load(s) if isinstance(meta, dict): return meta else: return None else: lines.append(line) ================================================ FILE: urubu/tests/__init__.py ================================================ import contextlib, os @contextlib.contextmanager def cd(path): """context manager to change directory temporarily. From activestate recipes. """ prev_cwd = os.getcwd() os.chdir(path) try: yield finally: os.chdir(prev_cwd) # reused from MyHDL import pytest class raises_kind(object): def __init__(self, exc, kind): self.exc = exc self.kind = kind def __enter__(self): return None def __exit__(self, *tp): __tracebackhide__ = True if tp[0] is None: pytest.fail("DID NOT RAISE") assert tp[1].kind == self.kind return issubclass(tp[0], self.exc) ================================================ FILE: urubu/tests/ambig_ref/_build/github.html ================================================ github
================================================ FILE: urubu/tests/ambig_ref/_build/index.html ================================================ test
================================================ FILE: urubu/tests/ambig_ref/_build/page.html ================================================ page
================================================ FILE: urubu/tests/ambig_ref/_layouts/_base.html ================================================ {{this.title}} {% set bootstrap = "3.1.1" %} {% if site.bootstrap %} {% set bootstrap = site.bootstrap %} {% endif %} {% if site.bootswatch %} {% set theme_path = "bootswatch/"+ bootstrap + '/' + site.bootswatch %} {% else %} {% set theme_path = "bootstrap/" + bootstrap + "/css" %} {% endif %} {% set url_prefix = '' %} {% if site.baseurl %} {% set url_prefix = '/' + site.baseurl %} {% endif %} {% set navbar_style = "navbar-default" %} {% if site.navbar_inverse %} {% set navbar_style = "navbar-inverse" %} {% endif %} {% set navbar_right_items = 2 %} {% if site.navbar_right_items %} {% set navbar_right_items = site.navbar_right_items %} {% endif %} {% block body %} {% endblock %} ================================================ FILE: urubu/tests/ambig_ref/_layouts/page.html ================================================ {% extends "_base.html" %} {% block body %}
{% block content %}
{{this.body}}
{% endblock %}
{% block sidebar %} {% if this.toc %} {% endif %} {% endblock %}
{% if this.pager %} {% endif %}
{% endblock %} ================================================ FILE: urubu/tests/ambig_ref/_site.yml ================================================ brand: Urubu bootswatch: null navbar_inverse: false bootstrap: 3.3.4 ignore_patterns: ['*.py', 'README.md'] reflinks: jandecaluwe: url: ttp://www.jandecaluwe.com title: Jan Decaluwe myhdl_site: url: http://www.myhdl.org title: MyHDL website dev_myhdl_site: url: http://dev.myhdl.org title: MyHDL development website content_license: url: http://creativecommons.org/licenses/by-sa/3.0/ title: CC-BY-SA License software_license: url: http://www.gnu.org/licenses/agpl-3.0.txt title: GNU Affero General Public License bitbucket: url: http://www.bitbucket.com title: Bitbucket github: url: http://www.github.com title: GitHub markdown: url: http://daringfireball.net/projects/markdown/ title: Markdown markdown_extra: url: http://pythonhosted.org/Markdown/extensions/extra.html title: Markdown Extra python_markdown: url: http://pythonhosted.org/Markdown/ title: Python-Markdown pygments: url: http://pygments.org title: Pygments jinja2: url: http://jinja.pocoo.org title: Jinja2 bootstrap: url: http://getbootstrap.com title: Bootstrap bootswatch: url: http://bootswatch.com title: Bootswatch pyyaml: url: http://pyyaml.org title: PyYAML jekyll: url: http://jekyllrb.com title: Jekyll pelican: url: http://getpelican.com title: Pelican virtualenv: url: http://www.virtualenv.org/en/latest/virtualenv.html title: virtualenv urubu_repo: url: https://github.com/jandecaluwe/urubu title: Urubu repo tables: url: http://pythonhosted.org/Markdown/extensions/tables.html title: Tables abbrev: url: http://pythonhosted.org/Markdown/extensions/abbreviations.html title: Abbrevations attr_list: url: http://pythonhosted.org/Markdown/extensions/attr_list.html title: Attribute lists def_list: url: http://pythonhosted.org/Markdown/extensions/definition_lists.html title: Definition Lists fenced_code: url: http://pythonhosted.org/Markdown/extensions/fenced_code_blocks.html title: Fenced Code Blocks markdown_checklist: url: https://github.com/FND/markdown-checklist title: GitHub style Task Lists code_hilite: url: http://pythonhosted.org/Markdown/extensions/code_hilite.html title: CodeHilite urubu-quickstart: url: http://urubu-quickstart.jandecaluwe.com title: Urubu Quickstart ================================================ FILE: urubu/tests/ambig_ref/github.md ================================================ --- title: github layout: page --- ================================================ FILE: urubu/tests/ambig_ref/index.md ================================================ --- title: test layout: page content: - github - page --- ================================================ FILE: urubu/tests/ambig_ref/page.md ================================================ --- title: page layout: page --- ================================================ FILE: urubu/tests/ambig_ref_md/_layouts/_base.html ================================================ {{this.title}} {% set bootstrap = "3.1.1" %} {% if site.bootstrap %} {% set bootstrap = site.bootstrap %} {% endif %} {% if site.bootswatch %} {% set theme_path = "bootswatch/"+ bootstrap + '/' + site.bootswatch %} {% else %} {% set theme_path = "bootstrap/" + bootstrap + "/css" %} {% endif %} {% set url_prefix = '' %} {% if site.baseurl %} {% set url_prefix = '/' + site.baseurl %} {% endif %} {% set navbar_style = "navbar-default" %} {% if site.navbar_inverse %} {% set navbar_style = "navbar-inverse" %} {% endif %} {% set navbar_right_items = 2 %} {% if site.navbar_right_items %} {% set navbar_right_items = site.navbar_right_items %} {% endif %} {% block body %} {% endblock %} ================================================ FILE: urubu/tests/ambig_ref_md/_layouts/page.html ================================================ {% extends "_base.html" %} {% block body %}
{% block content %}
{{this.body}}
{% endblock %}
{% block sidebar %} {% if this.toc %} {% endif %} {% endblock %}
{% if this.pager %} {% endif %}
{% endblock %} ================================================ FILE: urubu/tests/ambig_ref_md/_site.yml ================================================ brand: Urubu bootswatch: null navbar_inverse: false bootstrap: 3.3.4 ignore_patterns: ['*.py', 'README.md'] reflinks: jandecaluwe: url: ttp://www.jandecaluwe.com title: Jan Decaluwe myhdl_site: url: http://www.myhdl.org title: MyHDL website dev_myhdl_site: url: http://dev.myhdl.org title: MyHDL development website content_license: url: http://creativecommons.org/licenses/by-sa/3.0/ title: CC-BY-SA License software_license: url: http://www.gnu.org/licenses/agpl-3.0.txt title: GNU Affero General Public License bitbucket: url: http://www.bitbucket.com title: Bitbucket github: url: http://www.github.com title: GitHub markdown: url: http://daringfireball.net/projects/markdown/ title: Markdown markdown_extra: url: http://pythonhosted.org/Markdown/extensions/extra.html title: Markdown Extra python_markdown: url: http://pythonhosted.org/Markdown/ title: Python-Markdown pygments: url: http://pygments.org title: Pygments jinja2: url: http://jinja.pocoo.org title: Jinja2 bootstrap: url: http://getbootstrap.com title: Bootstrap bootswatch: url: http://bootswatch.com title: Bootswatch pyyaml: url: http://pyyaml.org title: PyYAML jekyll: url: http://jekyllrb.com title: Jekyll pelican: url: http://getpelican.com title: Pelican virtualenv: url: http://www.virtualenv.org/en/latest/virtualenv.html title: virtualenv urubu_repo: url: https://github.com/jandecaluwe/urubu title: Urubu repo tables: url: http://pythonhosted.org/Markdown/extensions/tables.html title: Tables abbrev: url: http://pythonhosted.org/Markdown/extensions/abbreviations.html title: Abbrevations attr_list: url: http://pythonhosted.org/Markdown/extensions/attr_list.html title: Attribute lists def_list: url: http://pythonhosted.org/Markdown/extensions/definition_lists.html title: Definition Lists fenced_code: url: http://pythonhosted.org/Markdown/extensions/fenced_code_blocks.html title: Fenced Code Blocks markdown_checklist: url: https://github.com/FND/markdown-checklist title: GitHub style Task Lists code_hilite: url: http://pythonhosted.org/Markdown/extensions/code_hilite.html title: CodeHilite urubu-quickstart: url: http://urubu-quickstart.jandecaluwe.com title: Urubu Quickstart ================================================ FILE: urubu/tests/ambig_ref_md/github.md ================================================ --- title: github layout: page --- ================================================ FILE: urubu/tests/ambig_ref_md/index.md ================================================ --- title: test layout: page content: - page --- ================================================ FILE: urubu/tests/ambig_ref_md/page.md ================================================ --- title: page layout: page --- Ambiguous reference: [github]. ================================================ FILE: urubu/tests/ambig_refid/_build/index.html ================================================ test
================================================ FILE: urubu/tests/ambig_refid/_build/page.html ================================================ page
================================================ FILE: urubu/tests/ambig_refid/_layouts/_base.html ================================================ {{this.title}} {% set bootstrap = "3.1.1" %} {% if site.bootstrap %} {% set bootstrap = site.bootstrap %} {% endif %} {% if site.bootswatch %} {% set theme_path = "bootswatch/"+ bootstrap + '/' + site.bootswatch %} {% else %} {% set theme_path = "bootstrap/" + bootstrap + "/css" %} {% endif %} {% set url_prefix = '' %} {% if site.baseurl %} {% set url_prefix = '/' + site.baseurl %} {% endif %} {% set navbar_style = "navbar-default" %} {% if site.navbar_inverse %} {% set navbar_style = "navbar-inverse" %} {% endif %} {% set navbar_right_items = 2 %} {% if site.navbar_right_items %} {% set navbar_right_items = site.navbar_right_items %} {% endif %} {% block body %} {% endblock %} ================================================ FILE: urubu/tests/ambig_refid/_layouts/page.html ================================================ {% extends "_base.html" %} {% block body %}
{% block content %}
{{this.body}}
{% endblock %}
{% block sidebar %} {% if this.toc %} {% endif %} {% endblock %}
{% if this.pager %} {% endif %}
{% endblock %} ================================================ FILE: urubu/tests/ambig_refid/_site.yml ================================================ brand: Urubu bootswatch: null navbar_inverse: false bootstrap: 3.3.4 ignore_patterns: ['*.py', 'README.md'] reflinks: jandecaluwe: url: ttp://www.jandecaluwe.com title: Jan Decaluwe myhdl_site: url: http://www.myhdl.org title: MyHDL website dev_myhdl_site: url: http://dev.myhdl.org title: MyHDL development website content_license: url: http://creativecommons.org/licenses/by-sa/3.0/ title: CC-BY-SA License software_license: url: http://www.gnu.org/licenses/agpl-3.0.txt title: GNU Affero General Public License bitbucket: url: http://www.bitbucket.com title: Bitbucket github: url: http://www.github.com title: GitHub markdown: url: http://daringfireball.net/projects/markdown/ title: Markdown markdown_extra: url: http://pythonhosted.org/Markdown/extensions/extra.html title: Markdown Extra python_markdown: url: http://pythonhosted.org/Markdown/ title: Python-Markdown pygments: url: http://pygments.org title: Pygments jinja2: url: http://jinja.pocoo.org title: Jinja2 bootstrap: url: http://getbootstrap.com title: Bootstrap bootswatch: url: http://bootswatch.com title: Bootswatch pyyaml: url: http://pyyaml.org title: PyYAML jekyll: url: http://jekyllrb.com title: Jekyll pelican: url: http://getpelican.com title: Pelican virtualenv: url: http://www.virtualenv.org/en/latest/virtualenv.html title: virtualenv urubu_repo: url: https://github.com/jandecaluwe/urubu title: Urubu repo tables: url: http://pythonhosted.org/Markdown/extensions/tables.html title: Tables abbrev: url: http://pythonhosted.org/Markdown/extensions/abbreviations.html title: Abbrevations attr_list: url: http://pythonhosted.org/Markdown/extensions/attr_list.html title: Attribute lists def_list: url: http://pythonhosted.org/Markdown/extensions/definition_lists.html title: Definition Lists fenced_code: url: http://pythonhosted.org/Markdown/extensions/fenced_code_blocks.html title: Fenced Code Blocks markdown_checklist: url: https://github.com/FND/markdown-checklist title: GitHub style Task Lists code_hilite: url: http://pythonhosted.org/Markdown/extensions/code_hilite.html title: CodeHilite urubu-quickstart: url: http://urubu-quickstart.jandecaluwe.com title: Urubu Quickstart ================================================ FILE: urubu/tests/ambig_refid/index.md ================================================ --- title: test layout: page content: [] --- ================================================ FILE: urubu/tests/ambig_refid/page/index.md ================================================ --- title: pagedir layout: page content: [] --- ================================================ FILE: urubu/tests/ambig_refid/page.md ================================================ --- title: page layout: page --- ================================================ FILE: urubu/tests/date_format/_build/index.html ================================================ test
================================================ FILE: urubu/tests/date_format/_build/page.html ================================================ page
================================================ FILE: urubu/tests/date_format/_layouts/_base.html ================================================ {{this.title}} {% set bootstrap = "3.1.1" %} {% if site.bootstrap %} {% set bootstrap = site.bootstrap %} {% endif %} {% if site.bootswatch %} {% set theme_path = "bootswatch/"+ bootstrap + '/' + site.bootswatch %} {% else %} {% set theme_path = "bootstrap/" + bootstrap + "/css" %} {% endif %} {% set url_prefix = '' %} {% if site.baseurl %} {% set url_prefix = '/' + site.baseurl %} {% endif %} {% set navbar_style = "navbar-default" %} {% if site.navbar_inverse %} {% set navbar_style = "navbar-inverse" %} {% endif %} {% set navbar_right_items = 2 %} {% if site.navbar_right_items %} {% set navbar_right_items = site.navbar_right_items %} {% endif %} {% block body %} {% endblock %} ================================================ FILE: urubu/tests/date_format/_layouts/page.html ================================================ {% extends "_base.html" %} {% block body %}
{% block content %}
{{this.body}}
{% endblock %}
{% block sidebar %} {% if this.toc %} {% endif %} {% endblock %}
{% if this.pager %} {% endif %}
{% endblock %} ================================================ FILE: urubu/tests/date_format/_site.yml ================================================ brand: Urubu bootswatch: null navbar_inverse: false bootstrap: 3.3.4 ignore_patterns: ['*.py', 'README.md'] reflinks: jandecaluwe: url: ttp://www.jandecaluwe.com title: Jan Decaluwe myhdl_site: url: http://www.myhdl.org title: MyHDL website dev_myhdl_site: url: http://dev.myhdl.org title: MyHDL development website content_license: url: http://creativecommons.org/licenses/by-sa/3.0/ title: CC-BY-SA License software_license: url: http://www.gnu.org/licenses/agpl-3.0.txt title: GNU Affero General Public License bitbucket: url: http://www.bitbucket.com title: Bitbucket github: url: http://www.github.com title: GitHub markdown: url: http://daringfireball.net/projects/markdown/ title: Markdown markdown_extra: url: http://pythonhosted.org/Markdown/extensions/extra.html title: Markdown Extra python_markdown: url: http://pythonhosted.org/Markdown/ title: Python-Markdown pygments: url: http://pygments.org title: Pygments jinja2: url: http://jinja.pocoo.org title: Jinja2 bootstrap: url: http://getbootstrap.com title: Bootstrap bootswatch: url: http://bootswatch.com title: Bootswatch pyyaml: url: http://pyyaml.org title: PyYAML jekyll: url: http://jekyllrb.com title: Jekyll pelican: url: http://getpelican.com title: Pelican virtualenv: url: http://www.virtualenv.org/en/latest/virtualenv.html title: virtualenv urubu_repo: url: https://github.com/jandecaluwe/urubu title: Urubu repo tables: url: http://pythonhosted.org/Markdown/extensions/tables.html title: Tables abbrev: url: http://pythonhosted.org/Markdown/extensions/abbreviations.html title: Abbrevations attr_list: url: http://pythonhosted.org/Markdown/extensions/attr_list.html title: Attribute lists def_list: url: http://pythonhosted.org/Markdown/extensions/definition_lists.html title: Definition Lists fenced_code: url: http://pythonhosted.org/Markdown/extensions/fenced_code_blocks.html title: Fenced Code Blocks markdown_checklist: url: https://github.com/FND/markdown-checklist title: GitHub style Task Lists code_hilite: url: http://pythonhosted.org/Markdown/extensions/code_hilite.html title: CodeHilite urubu-quickstart: url: http://urubu-quickstart.jandecaluwe.com title: Urubu Quickstart ================================================ FILE: urubu/tests/date_format/index.md ================================================ --- title: test layout: page content: - page --- ================================================ FILE: urubu/tests/date_format/page.md ================================================ --- title: page layout: page date: Sept 12, 1999 --- ================================================ FILE: urubu/tests/ignore_patterns/README.md ================================================ --- title: README layout: page --- ================================================ FILE: urubu/tests/ignore_patterns/_build/index.html ================================================ test
================================================ FILE: urubu/tests/ignore_patterns/_build/page.html ================================================ page
================================================ FILE: urubu/tests/ignore_patterns/_layouts/_base.html ================================================ {{this.title}} {% set bootstrap = "3.1.1" %} {% if site.bootstrap %} {% set bootstrap = site.bootstrap %} {% endif %} {% if site.bootswatch %} {% set theme_path = "bootswatch/"+ bootstrap + '/' + site.bootswatch %} {% else %} {% set theme_path = "bootstrap/" + bootstrap + "/css" %} {% endif %} {% set url_prefix = '' %} {% if site.baseurl %} {% set url_prefix = '/' + site.baseurl %} {% endif %} {% set navbar_style = "navbar-default" %} {% if site.navbar_inverse %} {% set navbar_style = "navbar-inverse" %} {% endif %} {% set navbar_right_items = 2 %} {% if site.navbar_right_items %} {% set navbar_right_items = site.navbar_right_items %} {% endif %} {% block body %} {% endblock %} ================================================ FILE: urubu/tests/ignore_patterns/_layouts/page.html ================================================ {% extends "_base.html" %} {% block body %}
{% block content %}
{{this.body}}
{% endblock %}
{% block sidebar %} {% if this.toc %} {% endif %} {% endblock %}
{% if this.pager %} {% endif %}
{% endblock %} ================================================ FILE: urubu/tests/ignore_patterns/_site.yml ================================================ brand: Urubu bootswatch: null navbar_inverse: false bootstrap: 3.3.4 ignore_patterns: ['*.py', 'README.md'] reflinks: jandecaluwe: url: ttp://www.jandecaluwe.com title: Jan Decaluwe myhdl_site: url: http://www.myhdl.org title: MyHDL website dev_myhdl_site: url: http://dev.myhdl.org title: MyHDL development website content_license: url: http://creativecommons.org/licenses/by-sa/3.0/ title: CC-BY-SA License software_license: url: http://www.gnu.org/licenses/agpl-3.0.txt title: GNU Affero General Public License bitbucket: url: http://www.bitbucket.com title: Bitbucket github: url: http://www.github.com title: GitHub markdown: url: http://daringfireball.net/projects/markdown/ title: Markdown markdown_extra: url: http://pythonhosted.org/Markdown/extensions/extra.html title: Markdown Extra python_markdown: url: http://pythonhosted.org/Markdown/ title: Python-Markdown pygments: url: http://pygments.org title: Pygments jinja2: url: http://jinja.pocoo.org title: Jinja2 bootstrap: url: http://getbootstrap.com title: Bootstrap bootswatch: url: http://bootswatch.com title: Bootswatch pyyaml: url: http://pyyaml.org title: PyYAML jekyll: url: http://jekyllrb.com title: Jekyll pelican: url: http://getpelican.com title: Pelican virtualenv: url: http://www.virtualenv.org/en/latest/virtualenv.html title: virtualenv urubu_repo: url: https://github.com/jandecaluwe/urubu title: Urubu repo tables: url: http://pythonhosted.org/Markdown/extensions/tables.html title: Tables abbrev: url: http://pythonhosted.org/Markdown/extensions/abbreviations.html title: Abbrevations attr_list: url: http://pythonhosted.org/Markdown/extensions/attr_list.html title: Attribute lists def_list: url: http://pythonhosted.org/Markdown/extensions/definition_lists.html title: Definition Lists fenced_code: url: http://pythonhosted.org/Markdown/extensions/fenced_code_blocks.html title: Fenced Code Blocks markdown_checklist: url: https://github.com/FND/markdown-checklist title: GitHub style Task Lists code_hilite: url: http://pythonhosted.org/Markdown/extensions/code_hilite.html title: CodeHilite urubu-quickstart: url: http://urubu-quickstart.jandecaluwe.com title: Urubu Quickstart ================================================ FILE: urubu/tests/ignore_patterns/index.md ================================================ --- title: test layout: page content: [] --- ================================================ FILE: urubu/tests/ignore_patterns/page.md ================================================ --- title: page layout: page --- ================================================ FILE: urubu/tests/no_index/_build/index.html ================================================ test
================================================ FILE: urubu/tests/no_index/_build/page.html ================================================ page
================================================ FILE: urubu/tests/no_index/_layouts/_base.html ================================================ {{this.title}} {% set bootstrap = "3.1.1" %} {% if site.bootstrap %} {% set bootstrap = site.bootstrap %} {% endif %} {% if site.bootswatch %} {% set theme_path = "bootswatch/"+ bootstrap + '/' + site.bootswatch %} {% else %} {% set theme_path = "bootstrap/" + bootstrap + "/css" %} {% endif %} {% set url_prefix = '' %} {% if site.baseurl %} {% set url_prefix = '/' + site.baseurl %} {% endif %} {% set navbar_style = "navbar-default" %} {% if site.navbar_inverse %} {% set navbar_style = "navbar-inverse" %} {% endif %} {% set navbar_right_items = 2 %} {% if site.navbar_right_items %} {% set navbar_right_items = site.navbar_right_items %} {% endif %} {% block body %} {% endblock %} ================================================ FILE: urubu/tests/no_index/_layouts/page.html ================================================ {% extends "_base.html" %} {% block body %}
{% block content %}
{{this.body}}
{% endblock %}
{% block sidebar %} {% if this.toc %} {% endif %} {% endblock %}
{% if this.pager %} {% endif %}
{% endblock %} ================================================ FILE: urubu/tests/no_index/_site.yml ================================================ brand: Urubu bootswatch: null navbar_inverse: false bootstrap: 3.3.4 ignore_patterns: ['*.py', 'README.md'] reflinks: jandecaluwe: url: ttp://www.jandecaluwe.com title: Jan Decaluwe myhdl_site: url: http://www.myhdl.org title: MyHDL website dev_myhdl_site: url: http://dev.myhdl.org title: MyHDL development website content_license: url: http://creativecommons.org/licenses/by-sa/3.0/ title: CC-BY-SA License software_license: url: http://www.gnu.org/licenses/agpl-3.0.txt title: GNU Affero General Public License bitbucket: url: http://www.bitbucket.com title: Bitbucket github: url: http://www.github.com title: GitHub markdown: url: http://daringfireball.net/projects/markdown/ title: Markdown markdown_extra: url: http://pythonhosted.org/Markdown/extensions/extra.html title: Markdown Extra python_markdown: url: http://pythonhosted.org/Markdown/ title: Python-Markdown pygments: url: http://pygments.org title: Pygments jinja2: url: http://jinja.pocoo.org title: Jinja2 bootstrap: url: http://getbootstrap.com title: Bootstrap bootswatch: url: http://bootswatch.com title: Bootswatch pyyaml: url: http://pyyaml.org title: PyYAML jekyll: url: http://jekyllrb.com title: Jekyll pelican: url: http://getpelican.com title: Pelican virtualenv: url: http://www.virtualenv.org/en/latest/virtualenv.html title: virtualenv urubu_repo: url: https://github.com/jandecaluwe/urubu title: Urubu repo tables: url: http://pythonhosted.org/Markdown/extensions/tables.html title: Tables abbrev: url: http://pythonhosted.org/Markdown/extensions/abbreviations.html title: Abbrevations attr_list: url: http://pythonhosted.org/Markdown/extensions/attr_list.html title: Attribute lists def_list: url: http://pythonhosted.org/Markdown/extensions/definition_lists.html title: Definition Lists fenced_code: url: http://pythonhosted.org/Markdown/extensions/fenced_code_blocks.html title: Fenced Code Blocks markdown_checklist: url: https://github.com/FND/markdown-checklist title: GitHub style Task Lists code_hilite: url: http://pythonhosted.org/Markdown/extensions/code_hilite.html title: CodeHilite urubu-quickstart: url: http://urubu-quickstart.jandecaluwe.com title: Urubu Quickstart ================================================ FILE: urubu/tests/no_index/folder/page.md ================================================ --- title: page layout: page --- ================================================ FILE: urubu/tests/no_index/index.md ================================================ --- title: test layout: page content: - page --- ================================================ FILE: urubu/tests/no_index/page.md ================================================ --- title: page layout: page --- ================================================ FILE: urubu/tests/no_yamlfm/_build/index.html ================================================ test
================================================ FILE: urubu/tests/no_yamlfm/_layouts/_base.html ================================================ {{this.title}} {% set bootstrap = "3.1.1" %} {% if site.bootstrap %} {% set bootstrap = site.bootstrap %} {% endif %} {% if site.bootswatch %} {% set theme_path = "bootswatch/"+ bootstrap + '/' + site.bootswatch %} {% else %} {% set theme_path = "bootstrap/" + bootstrap + "/css" %} {% endif %} {% set url_prefix = '' %} {% if site.baseurl %} {% set url_prefix = '/' + site.baseurl %} {% endif %} {% set navbar_style = "navbar-default" %} {% if site.navbar_inverse %} {% set navbar_style = "navbar-inverse" %} {% endif %} {% set navbar_right_items = 2 %} {% if site.navbar_right_items %} {% set navbar_right_items = site.navbar_right_items %} {% endif %} {% block body %} {% endblock %} ================================================ FILE: urubu/tests/no_yamlfm/_layouts/page.html ================================================ {% extends "_base.html" %} {% block body %}
{% block content %}
{{this.body}}
{% endblock %}
{% block sidebar %} {% if this.toc %} {% endif %} {% endblock %}
{% if this.pager %} {% endif %}
{% endblock %} ================================================ FILE: urubu/tests/no_yamlfm/_site.yml ================================================ brand: Urubu bootswatch: null navbar_inverse: false bootstrap: 3.3.4 ignore_patterns: ['*.py', 'README.md'] reflinks: jandecaluwe: url: ttp://www.jandecaluwe.com title: Jan Decaluwe myhdl_site: url: http://www.myhdl.org title: MyHDL website dev_myhdl_site: url: http://dev.myhdl.org title: MyHDL development website content_license: url: http://creativecommons.org/licenses/by-sa/3.0/ title: CC-BY-SA License software_license: url: http://www.gnu.org/licenses/agpl-3.0.txt title: GNU Affero General Public License bitbucket: url: http://www.bitbucket.com title: Bitbucket github: url: http://www.github.com title: GitHub markdown: url: http://daringfireball.net/projects/markdown/ title: Markdown markdown_extra: url: http://pythonhosted.org/Markdown/extensions/extra.html title: Markdown Extra python_markdown: url: http://pythonhosted.org/Markdown/ title: Python-Markdown pygments: url: http://pygments.org title: Pygments jinja2: url: http://jinja.pocoo.org title: Jinja2 bootstrap: url: http://getbootstrap.com title: Bootstrap bootswatch: url: http://bootswatch.com title: Bootswatch pyyaml: url: http://pyyaml.org title: PyYAML jekyll: url: http://jekyllrb.com title: Jekyll pelican: url: http://getpelican.com title: Pelican virtualenv: url: http://www.virtualenv.org/en/latest/virtualenv.html title: virtualenv urubu_repo: url: https://github.com/jandecaluwe/urubu title: Urubu repo tables: url: http://pythonhosted.org/Markdown/extensions/tables.html title: Tables abbrev: url: http://pythonhosted.org/Markdown/extensions/abbreviations.html title: Abbrevations attr_list: url: http://pythonhosted.org/Markdown/extensions/attr_list.html title: Attribute lists def_list: url: http://pythonhosted.org/Markdown/extensions/definition_lists.html title: Definition Lists fenced_code: url: http://pythonhosted.org/Markdown/extensions/fenced_code_blocks.html title: Fenced Code Blocks markdown_checklist: url: https://github.com/FND/markdown-checklist title: GitHub style Task Lists code_hilite: url: http://pythonhosted.org/Markdown/extensions/code_hilite.html title: CodeHilite urubu-quickstart: url: http://urubu-quickstart.jandecaluwe.com title: Urubu Quickstart ================================================ FILE: urubu/tests/no_yamlfm/index.md ================================================ --- title: test layout: page content: [] --- ================================================ FILE: urubu/tests/no_yamlfm/page.md ================================================ ================================================ FILE: urubu/tests/test_doc.py ================================================ import os, sys from sh import git, touch from urubu import project, UrubuError from urubu.tests import cd def test_doc(): with cd('../../doc'): sys.path.insert(0, os.getcwd()) project.build() touch('_build/.nojekyll') d = git('--no-pager', 'diff', '-w', '--', '_build') if d: print(d) raise ValueError('Diffs in website') _python = None test_doc() ================================================ FILE: urubu/tests/test_errors.py ================================================ import os from urubu import UrubuError, project from urubu.project import _error from urubu.tests import cd, raises_kind def test_undef_reflink_title(): with cd('undef_reflink_title'): with raises_kind(UrubuError, _error.undef_reflink_key): project.build() def test_undef_reflink_url(): with cd('undef_reflink_url'): with raises_kind(UrubuError, _error.undef_reflink_key): project.build() def test_ambig_ref_md(): with cd('ambig_ref_md'): with raises_kind(UrubuError, _error.ambig_ref_md): project.build() def test_ambig_refid(): with cd('ambig_refid'): with raises_kind(UrubuError, _error.ambig_refid): project.build() def test_ambig_ref(): with cd('ambig_ref'): with raises_kind(UrubuError, _error.ambig_ref): project.build() def test_date_format(): with cd('date_format'): with raises_kind(UrubuError, _error.date_format): project.build() def test_undef_reflink_title(): with cd('undef_reflink_title'): with raises_kind(UrubuError, _error.undef_reflink_key): project.build() def test_undef_reflink_url(): with cd('undef_reflink_url'): with raises_kind(UrubuError, _error.undef_reflink_key): project.build() def test_ignore_patterns(): with cd('ignore_patterns'): project.build() assert not os.path.exists(os.path.join('_build', 'README.html')) assert os.path.exists(os.path.join('_build', 'page.html')) def test_undef_content(): with cd('undef_content'): with raises_kind(UrubuError, _error.undef_content): project.build() def test_undef_key(): with cd('undef_key'): with raises_kind(UrubuError, _error.undef_key): project.build() def test_undef_layout(): with cd('undef_layout'): with raises_kind(UrubuError, _error.undef_info): project.build() def test_undef_ref(): with cd('undef_ref'): with raises_kind(UrubuError, _error.undef_ref): project.build() def test_no_index(): with cd('no_index'): with raises_kind(UrubuError, _error.no_index): project.build() ================================================ FILE: urubu/tests/test_warnings.py ================================================ import os import pytest from urubu import UrubuWarning, _warning, project from urubu.tests import cd def test_no_yamlfm(): with cd('no_yamlfm'): with pytest.warns(UrubuWarning) as record: project.build() print (record) assert len(record) == 1 assert _warning.no_yamlfm in str(record[0].message) def test_undef_tag_layout(): with cd('undef_tag_layout'): with pytest.warns(UrubuWarning) as record: project.build() print (record) assert len(record) == 1 assert _warning.undef_tag_layout in str(record[0].message) def test_undef_ref_md(): with cd('undef_ref_md'): with pytest.warns(UrubuWarning) as record: project.build() print (record) assert len(record) == 1 assert _warning.undef_ref_md in str(record[0].message) def test_undef_anchor(): with cd('undef_anchor'): with pytest.warns(UrubuWarning) as record: project.build() assert len(record) == 1 assert _warning.undef_anchor in str(record[0].message) ================================================ FILE: urubu/tests/undef_anchor/_build/index.html ================================================ test
================================================ FILE: urubu/tests/undef_anchor/_build/page.html ================================================ page

Define an anchor.

================================================ FILE: urubu/tests/undef_anchor/_build/page2.html ================================================ page

Reference to an anchor in a page: an anchor.

Reference an undefined anchor: an undefined anchor.

================================================ FILE: urubu/tests/undef_anchor/_layouts/_base.html ================================================ {{this.title}} {% set bootstrap = "3.1.1" %} {% if site.bootstrap %} {% set bootstrap = site.bootstrap %} {% endif %} {% if site.bootswatch %} {% set theme_path = "bootswatch/"+ bootstrap + '/' + site.bootswatch %} {% else %} {% set theme_path = "bootstrap/" + bootstrap + "/css" %} {% endif %} {% set url_prefix = '' %} {% if site.baseurl %} {% set url_prefix = '/' + site.baseurl %} {% endif %} {% set navbar_style = "navbar-default" %} {% if site.navbar_inverse %} {% set navbar_style = "navbar-inverse" %} {% endif %} {% set navbar_right_items = 2 %} {% if site.navbar_right_items %} {% set navbar_right_items = site.navbar_right_items %} {% endif %} {% block body %} {% endblock %} ================================================ FILE: urubu/tests/undef_anchor/_layouts/page.html ================================================ {% extends "_base.html" %} {% block body %}
{% block content %}
{{this.body}}
{% endblock %}
{% block sidebar %} {% if this.toc %} {% endif %} {% endblock %}
{% if this.pager %} {% endif %}
{% endblock %} ================================================ FILE: urubu/tests/undef_anchor/_site.yml ================================================ brand: Urubu bootswatch: null navbar_inverse: false bootstrap: 3.3.4 ignore_patterns: ['*.py', 'README.md'] reflinks: jandecaluwe: url: ttp://www.jandecaluwe.com title: Jan Decaluwe myhdl_site: url: http://www.myhdl.org title: MyHDL website dev_myhdl_site: url: http://dev.myhdl.org title: MyHDL development website content_license: url: http://creativecommons.org/licenses/by-sa/3.0/ title: CC-BY-SA License software_license: url: http://www.gnu.org/licenses/agpl-3.0.txt title: GNU Affero General Public License bitbucket: url: http://www.bitbucket.com title: Bitbucket github: url: http://www.github.com title: GitHub markdown: url: http://daringfireball.net/projects/markdown/ title: Markdown markdown_extra: url: http://pythonhosted.org/Markdown/extensions/extra.html title: Markdown Extra python_markdown: url: http://pythonhosted.org/Markdown/ title: Python-Markdown pygments: url: http://pygments.org title: Pygments jinja2: url: http://jinja.pocoo.org title: Jinja2 bootstrap: url: http://getbootstrap.com title: Bootstrap bootswatch: url: http://bootswatch.com title: Bootswatch pyyaml: url: http://pyyaml.org title: PyYAML jekyll: url: http://jekyllrb.com title: Jekyll pelican: url: http://getpelican.com title: Pelican virtualenv: url: http://www.virtualenv.org/en/latest/virtualenv.html title: virtualenv urubu_repo: url: https://github.com/jandecaluwe/urubu title: Urubu repo tables: url: http://pythonhosted.org/Markdown/extensions/tables.html title: Tables abbrev: url: http://pythonhosted.org/Markdown/extensions/abbreviations.html title: Abbrevations attr_list: url: http://pythonhosted.org/Markdown/extensions/attr_list.html title: Attribute lists def_list: url: http://pythonhosted.org/Markdown/extensions/definition_lists.html title: Definition Lists fenced_code: url: http://pythonhosted.org/Markdown/extensions/fenced_code_blocks.html title: Fenced Code Blocks markdown_checklist: url: https://github.com/FND/markdown-checklist title: GitHub style Task Lists code_hilite: url: http://pythonhosted.org/Markdown/extensions/code_hilite.html title: CodeHilite urubu-quickstart: url: http://urubu-quickstart.jandecaluwe.com title: Urubu Quickstart ================================================ FILE: urubu/tests/undef_anchor/index.md ================================================ --- title: test layout: page content: [] --- ================================================ FILE: urubu/tests/undef_anchor/page.md ================================================ --- title: page layout: page --- Define an anchor. {: #an-anchor} ================================================ FILE: urubu/tests/undef_anchor/page2.md ================================================ --- title: page layout: page --- Reference to an anchor in a [page]: [page#an anchor]. Reference an undefined anchor: [page#an undefined anchor]. ================================================ FILE: urubu/tests/undef_content/_build/index.html ================================================ test
================================================ FILE: urubu/tests/undef_content/_build/page.html ================================================ page
================================================ FILE: urubu/tests/undef_content/_layouts/_base.html ================================================ {{this.title}} {% set bootstrap = "3.1.1" %} {% if site.bootstrap %} {% set bootstrap = site.bootstrap %} {% endif %} {% if site.bootswatch %} {% set theme_path = "bootswatch/"+ bootstrap + '/' + site.bootswatch %} {% else %} {% set theme_path = "bootstrap/" + bootstrap + "/css" %} {% endif %} {% set url_prefix = '' %} {% if site.baseurl %} {% set url_prefix = '/' + site.baseurl %} {% endif %} {% set navbar_style = "navbar-default" %} {% if site.navbar_inverse %} {% set navbar_style = "navbar-inverse" %} {% endif %} {% set navbar_right_items = 2 %} {% if site.navbar_right_items %} {% set navbar_right_items = site.navbar_right_items %} {% endif %} {% block body %} {% endblock %} ================================================ FILE: urubu/tests/undef_content/_layouts/page.html ================================================ {% extends "_base.html" %} {% block body %}
{% block content %}
{{this.body}}
{% endblock %}
{% block sidebar %} {% if this.toc %} {% endif %} {% endblock %}
{% if this.pager %} {% endif %}
{% endblock %} ================================================ FILE: urubu/tests/undef_content/_site.yml ================================================ brand: Urubu bootswatch: null navbar_inverse: false bootstrap: 3.3.4 ignore_patterns: ['*.py', 'README.md'] reflinks: jandecaluwe: url: ttp://www.jandecaluwe.com title: Jan Decaluwe myhdl_site: url: http://www.myhdl.org title: MyHDL website dev_myhdl_site: url: http://dev.myhdl.org title: MyHDL development website content_license: url: http://creativecommons.org/licenses/by-sa/3.0/ title: CC-BY-SA License software_license: url: http://www.gnu.org/licenses/agpl-3.0.txt title: GNU Affero General Public License bitbucket: url: http://www.bitbucket.com title: Bitbucket github: url: http://www.github.com title: GitHub markdown: url: http://daringfireball.net/projects/markdown/ title: Markdown markdown_extra: url: http://pythonhosted.org/Markdown/extensions/extra.html title: Markdown Extra python_markdown: url: http://pythonhosted.org/Markdown/ title: Python-Markdown pygments: url: http://pygments.org title: Pygments jinja2: url: http://jinja.pocoo.org title: Jinja2 bootstrap: url: http://getbootstrap.com title: Bootstrap bootswatch: url: http://bootswatch.com title: Bootswatch pyyaml: url: http://pyyaml.org title: PyYAML jekyll: url: http://jekyllrb.com title: Jekyll pelican: url: http://getpelican.com title: Pelican virtualenv: url: http://www.virtualenv.org/en/latest/virtualenv.html title: virtualenv urubu_repo: url: https://github.com/jandecaluwe/urubu title: Urubu repo tables: url: http://pythonhosted.org/Markdown/extensions/tables.html title: Tables abbrev: url: http://pythonhosted.org/Markdown/extensions/abbreviations.html title: Abbrevations attr_list: url: http://pythonhosted.org/Markdown/extensions/attr_list.html title: Attribute lists def_list: url: http://pythonhosted.org/Markdown/extensions/definition_lists.html title: Definition Lists fenced_code: url: http://pythonhosted.org/Markdown/extensions/fenced_code_blocks.html title: Fenced Code Blocks markdown_checklist: url: https://github.com/FND/markdown-checklist title: GitHub style Task Lists code_hilite: url: http://pythonhosted.org/Markdown/extensions/code_hilite.html title: CodeHilite urubu-quickstart: url: http://urubu-quickstart.jandecaluwe.com title: Urubu Quickstart ================================================ FILE: urubu/tests/undef_content/index.md ================================================ --- title: test layout: page --- ================================================ FILE: urubu/tests/undef_content/page.md ================================================ --- title: page layout: page --- ================================================ FILE: urubu/tests/undef_key/_build/folder/index.html ================================================ test
================================================ FILE: urubu/tests/undef_key/_build/folder/item.d ================================================ --- title: page layout: page --- ================================================ FILE: urubu/tests/undef_key/_build/index.html ================================================ test
================================================ FILE: urubu/tests/undef_key/_build/page.html ================================================ page
================================================ FILE: urubu/tests/undef_key/_layouts/_base.html ================================================ {{this.title}} {% set bootstrap = "3.1.1" %} {% if site.bootstrap %} {% set bootstrap = site.bootstrap %} {% endif %} {% if site.bootswatch %} {% set theme_path = "bootswatch/"+ bootstrap + '/' + site.bootswatch %} {% else %} {% set theme_path = "bootstrap/" + bootstrap + "/css" %} {% endif %} {% set url_prefix = '' %} {% if site.baseurl %} {% set url_prefix = '/' + site.baseurl %} {% endif %} {% set navbar_style = "navbar-default" %} {% if site.navbar_inverse %} {% set navbar_style = "navbar-inverse" %} {% endif %} {% set navbar_right_items = 2 %} {% if site.navbar_right_items %} {% set navbar_right_items = site.navbar_right_items %} {% endif %} {% block body %} {% endblock %} ================================================ FILE: urubu/tests/undef_key/_layouts/page.html ================================================ {% extends "_base.html" %} {% block body %}
{% block content %}
{{this.body}}
{% endblock %}
{% block sidebar %} {% if this.toc %} {% endif %} {% endblock %}
{% if this.pager %} {% endif %}
{% endblock %} ================================================ FILE: urubu/tests/undef_key/_site.yml ================================================ brand: Urubu bootswatch: null navbar_inverse: false bootstrap: 3.3.4 ignore_patterns: ['*.py', 'README.md'] reflinks: jandecaluwe: url: ttp://www.jandecaluwe.com title: Jan Decaluwe myhdl_site: url: http://www.myhdl.org title: MyHDL website dev_myhdl_site: url: http://dev.myhdl.org title: MyHDL development website content_license: url: http://creativecommons.org/licenses/by-sa/3.0/ title: CC-BY-SA License software_license: url: http://www.gnu.org/licenses/agpl-3.0.txt title: GNU Affero General Public License bitbucket: url: http://www.bitbucket.com title: Bitbucket github: url: http://www.github.com title: GitHub markdown: url: http://daringfireball.net/projects/markdown/ title: Markdown markdown_extra: url: http://pythonhosted.org/Markdown/extensions/extra.html title: Markdown Extra python_markdown: url: http://pythonhosted.org/Markdown/ title: Python-Markdown pygments: url: http://pygments.org title: Pygments jinja2: url: http://jinja.pocoo.org title: Jinja2 bootstrap: url: http://getbootstrap.com title: Bootstrap bootswatch: url: http://bootswatch.com title: Bootswatch pyyaml: url: http://pyyaml.org title: PyYAML jekyll: url: http://jekyllrb.com title: Jekyll pelican: url: http://getpelican.com title: Pelican virtualenv: url: http://www.virtualenv.org/en/latest/virtualenv.html title: virtualenv urubu_repo: url: https://github.com/jandecaluwe/urubu title: Urubu repo tables: url: http://pythonhosted.org/Markdown/extensions/tables.html title: Tables abbrev: url: http://pythonhosted.org/Markdown/extensions/abbreviations.html title: Abbrevations attr_list: url: http://pythonhosted.org/Markdown/extensions/attr_list.html title: Attribute lists def_list: url: http://pythonhosted.org/Markdown/extensions/definition_lists.html title: Definition Lists fenced_code: url: http://pythonhosted.org/Markdown/extensions/fenced_code_blocks.html title: Fenced Code Blocks markdown_checklist: url: https://github.com/FND/markdown-checklist title: GitHub style Task Lists code_hilite: url: http://pythonhosted.org/Markdown/extensions/code_hilite.html title: CodeHilite urubu-quickstart: url: http://urubu-quickstart.jandecaluwe.com title: Urubu Quickstart ================================================ FILE: urubu/tests/undef_key/folder/index.md ================================================ --- title: test layout: page order: nr --- ================================================ FILE: urubu/tests/undef_key/folder/item.md ================================================ --- title: page layout: page --- ================================================ FILE: urubu/tests/undef_key/index.md ================================================ --- title: test layout: page content: - folder --- ================================================ FILE: urubu/tests/undef_key/page.md ================================================ --- title: page layout: page --- ================================================ FILE: urubu/tests/undef_layout/_build/index.html ================================================ test
================================================ FILE: urubu/tests/undef_layout/_build/page.html ================================================ page
================================================ FILE: urubu/tests/undef_layout/_layouts/_base.html ================================================ {{this.title}} {% set bootstrap = "3.1.1" %} {% if site.bootstrap %} {% set bootstrap = site.bootstrap %} {% endif %} {% if site.bootswatch %} {% set theme_path = "bootswatch/"+ bootstrap + '/' + site.bootswatch %} {% else %} {% set theme_path = "bootstrap/" + bootstrap + "/css" %} {% endif %} {% set url_prefix = '' %} {% if site.baseurl %} {% set url_prefix = '/' + site.baseurl %} {% endif %} {% set navbar_style = "navbar-default" %} {% if site.navbar_inverse %} {% set navbar_style = "navbar-inverse" %} {% endif %} {% set navbar_right_items = 2 %} {% if site.navbar_right_items %} {% set navbar_right_items = site.navbar_right_items %} {% endif %} {% block body %} {% endblock %} ================================================ FILE: urubu/tests/undef_layout/_layouts/page.html ================================================ {% extends "_base.html" %} {% block body %}
{% block content %}
{{this.body}}
{% endblock %}
{% block sidebar %} {% if this.toc %} {% endif %} {% endblock %}
{% if this.pager %} {% endif %}
{% endblock %} ================================================ FILE: urubu/tests/undef_layout/_site.yml ================================================ brand: Urubu bootswatch: null navbar_inverse: false bootstrap: 3.3.4 ignore_patterns: ['*.py', 'README.md'] reflinks: jandecaluwe: url: ttp://www.jandecaluwe.com title: Jan Decaluwe myhdl_site: url: http://www.myhdl.org title: MyHDL website dev_myhdl_site: url: http://dev.myhdl.org title: MyHDL development website content_license: url: http://creativecommons.org/licenses/by-sa/3.0/ title: CC-BY-SA License software_license: url: http://www.gnu.org/licenses/agpl-3.0.txt title: GNU Affero General Public License bitbucket: url: http://www.bitbucket.com title: Bitbucket github: url: http://www.github.com title: GitHub markdown: url: http://daringfireball.net/projects/markdown/ title: Markdown markdown_extra: url: http://pythonhosted.org/Markdown/extensions/extra.html title: Markdown Extra python_markdown: url: http://pythonhosted.org/Markdown/ title: Python-Markdown pygments: url: http://pygments.org title: Pygments jinja2: url: http://jinja.pocoo.org title: Jinja2 bootstrap: url: http://getbootstrap.com title: Bootstrap bootswatch: url: http://bootswatch.com title: Bootswatch pyyaml: url: http://pyyaml.org title: PyYAML jekyll: url: http://jekyllrb.com title: Jekyll pelican: url: http://getpelican.com title: Pelican virtualenv: url: http://www.virtualenv.org/en/latest/virtualenv.html title: virtualenv urubu_repo: url: https://github.com/jandecaluwe/urubu title: Urubu repo tables: url: http://pythonhosted.org/Markdown/extensions/tables.html title: Tables abbrev: url: http://pythonhosted.org/Markdown/extensions/abbreviations.html title: Abbrevations attr_list: url: http://pythonhosted.org/Markdown/extensions/attr_list.html title: Attribute lists def_list: url: http://pythonhosted.org/Markdown/extensions/definition_lists.html title: Definition Lists fenced_code: url: http://pythonhosted.org/Markdown/extensions/fenced_code_blocks.html title: Fenced Code Blocks markdown_checklist: url: https://github.com/FND/markdown-checklist title: GitHub style Task Lists code_hilite: url: http://pythonhosted.org/Markdown/extensions/code_hilite.html title: CodeHilite urubu-quickstart: url: http://urubu-quickstart.jandecaluwe.com title: Urubu Quickstart ================================================ FILE: urubu/tests/undef_layout/index.md ================================================ --- title: test layout: page content: - page --- ================================================ FILE: urubu/tests/undef_layout/page.md ================================================ --- title: page --- ================================================ FILE: urubu/tests/undef_ref/_build/index.html ================================================ test
================================================ FILE: urubu/tests/undef_ref/_build/page.html ================================================ page
================================================ FILE: urubu/tests/undef_ref/_layouts/_base.html ================================================ {{this.title}} {% set bootstrap = "3.1.1" %} {% if site.bootstrap %} {% set bootstrap = site.bootstrap %} {% endif %} {% if site.bootswatch %} {% set theme_path = "bootswatch/"+ bootstrap + '/' + site.bootswatch %} {% else %} {% set theme_path = "bootstrap/" + bootstrap + "/css" %} {% endif %} {% set url_prefix = '' %} {% if site.baseurl %} {% set url_prefix = '/' + site.baseurl %} {% endif %} {% set navbar_style = "navbar-default" %} {% if site.navbar_inverse %} {% set navbar_style = "navbar-inverse" %} {% endif %} {% set navbar_right_items = 2 %} {% if site.navbar_right_items %} {% set navbar_right_items = site.navbar_right_items %} {% endif %} {% block body %} {% endblock %} ================================================ FILE: urubu/tests/undef_ref/_layouts/page.html ================================================ {% extends "_base.html" %} {% block body %}
{% block content %}
{{this.body}}
{% endblock %}
{% block sidebar %} {% if this.toc %} {% endif %} {% endblock %}
{% if this.pager %} {% endif %}
{% endblock %} ================================================ FILE: urubu/tests/undef_ref/_site.yml ================================================ brand: Urubu bootswatch: null navbar_inverse: false bootstrap: 3.3.4 ignore_patterns: ['*.py', 'README.md'] reflinks: jandecaluwe: url: ttp://www.jandecaluwe.com title: Jan Decaluwe myhdl_site: url: http://www.myhdl.org title: MyHDL website dev_myhdl_site: url: http://dev.myhdl.org title: MyHDL development website content_license: url: http://creativecommons.org/licenses/by-sa/3.0/ title: CC-BY-SA License software_license: url: http://www.gnu.org/licenses/agpl-3.0.txt title: GNU Affero General Public License bitbucket: url: http://www.bitbucket.com title: Bitbucket github: url: http://www.github.com title: GitHub markdown: url: http://daringfireball.net/projects/markdown/ title: Markdown markdown_extra: url: http://pythonhosted.org/Markdown/extensions/extra.html title: Markdown Extra python_markdown: url: http://pythonhosted.org/Markdown/ title: Python-Markdown pygments: url: http://pygments.org title: Pygments jinja2: url: http://jinja.pocoo.org title: Jinja2 bootstrap: url: http://getbootstrap.com title: Bootstrap bootswatch: url: http://bootswatch.com title: Bootswatch pyyaml: url: http://pyyaml.org title: PyYAML jekyll: url: http://jekyllrb.com title: Jekyll pelican: url: http://getpelican.com title: Pelican virtualenv: url: http://www.virtualenv.org/en/latest/virtualenv.html title: virtualenv urubu_repo: url: https://github.com/jandecaluwe/urubu title: Urubu repo tables: url: http://pythonhosted.org/Markdown/extensions/tables.html title: Tables abbrev: url: http://pythonhosted.org/Markdown/extensions/abbreviations.html title: Abbrevations attr_list: url: http://pythonhosted.org/Markdown/extensions/attr_list.html title: Attribute lists def_list: url: http://pythonhosted.org/Markdown/extensions/definition_lists.html title: Definition Lists fenced_code: url: http://pythonhosted.org/Markdown/extensions/fenced_code_blocks.html title: Fenced Code Blocks markdown_checklist: url: https://github.com/FND/markdown-checklist title: GitHub style Task Lists code_hilite: url: http://pythonhosted.org/Markdown/extensions/code_hilite.html title: CodeHilite urubu-quickstart: url: http://urubu-quickstart.jandecaluwe.com title: Urubu Quickstart ================================================ FILE: urubu/tests/undef_ref/index.md ================================================ --- title: test layout: page content: - undefined_page - page --- ================================================ FILE: urubu/tests/undef_ref/page.md ================================================ --- title: page layout: page --- ================================================ FILE: urubu/tests/undef_ref_md/_build/index.html ================================================ test
================================================ FILE: urubu/tests/undef_ref_md/_build/page.html ================================================ page
================================================ FILE: urubu/tests/undef_ref_md/_build/page2.html ================================================ page

Reference an undefined page: [undefined_page].

================================================ FILE: urubu/tests/undef_ref_md/_layouts/_base.html ================================================ {{this.title}} {% set bootstrap = "3.1.1" %} {% if site.bootstrap %} {% set bootstrap = site.bootstrap %} {% endif %} {% if site.bootswatch %} {% set theme_path = "bootswatch/"+ bootstrap + '/' + site.bootswatch %} {% else %} {% set theme_path = "bootstrap/" + bootstrap + "/css" %} {% endif %} {% set url_prefix = '' %} {% if site.baseurl %} {% set url_prefix = '/' + site.baseurl %} {% endif %} {% set navbar_style = "navbar-default" %} {% if site.navbar_inverse %} {% set navbar_style = "navbar-inverse" %} {% endif %} {% set navbar_right_items = 2 %} {% if site.navbar_right_items %} {% set navbar_right_items = site.navbar_right_items %} {% endif %} {% block body %} {% endblock %} ================================================ FILE: urubu/tests/undef_ref_md/_layouts/page.html ================================================ {% extends "_base.html" %} {% block body %}
{% block content %}
{{this.body}}
{% endblock %}
{% block sidebar %} {% if this.toc %} {% endif %} {% endblock %}
{% if this.pager %} {% endif %}
{% endblock %} ================================================ FILE: urubu/tests/undef_ref_md/_site.yml ================================================ brand: Urubu bootswatch: null navbar_inverse: false bootstrap: 3.3.4 ignore_patterns: ['*.py', 'README.md'] reflinks: jandecaluwe: url: ttp://www.jandecaluwe.com title: Jan Decaluwe myhdl_site: url: http://www.myhdl.org title: MyHDL website dev_myhdl_site: url: http://dev.myhdl.org title: MyHDL development website content_license: url: http://creativecommons.org/licenses/by-sa/3.0/ title: CC-BY-SA License software_license: url: http://www.gnu.org/licenses/agpl-3.0.txt title: GNU Affero General Public License bitbucket: url: http://www.bitbucket.com title: Bitbucket github: url: http://www.github.com title: GitHub markdown: url: http://daringfireball.net/projects/markdown/ title: Markdown markdown_extra: url: http://pythonhosted.org/Markdown/extensions/extra.html title: Markdown Extra python_markdown: url: http://pythonhosted.org/Markdown/ title: Python-Markdown pygments: url: http://pygments.org title: Pygments jinja2: url: http://jinja.pocoo.org title: Jinja2 bootstrap: url: http://getbootstrap.com title: Bootstrap bootswatch: url: http://bootswatch.com title: Bootswatch pyyaml: url: http://pyyaml.org title: PyYAML jekyll: url: http://jekyllrb.com title: Jekyll pelican: url: http://getpelican.com title: Pelican virtualenv: url: http://www.virtualenv.org/en/latest/virtualenv.html title: virtualenv urubu_repo: url: https://github.com/jandecaluwe/urubu title: Urubu repo tables: url: http://pythonhosted.org/Markdown/extensions/tables.html title: Tables abbrev: url: http://pythonhosted.org/Markdown/extensions/abbreviations.html title: Abbrevations attr_list: url: http://pythonhosted.org/Markdown/extensions/attr_list.html title: Attribute lists def_list: url: http://pythonhosted.org/Markdown/extensions/definition_lists.html title: Definition Lists fenced_code: url: http://pythonhosted.org/Markdown/extensions/fenced_code_blocks.html title: Fenced Code Blocks markdown_checklist: url: https://github.com/FND/markdown-checklist title: GitHub style Task Lists code_hilite: url: http://pythonhosted.org/Markdown/extensions/code_hilite.html title: CodeHilite urubu-quickstart: url: http://urubu-quickstart.jandecaluwe.com title: Urubu Quickstart ================================================ FILE: urubu/tests/undef_ref_md/index.md ================================================ --- title: test layout: page content: [] --- ================================================ FILE: urubu/tests/undef_ref_md/page.md ================================================ --- title: page layout: page --- ================================================ FILE: urubu/tests/undef_ref_md/page2.md ================================================ --- title: page layout: page --- Reference an undefined page: [undefined_page]. ================================================ FILE: urubu/tests/undef_reflink_title/_build/index.html ================================================ test
================================================ FILE: urubu/tests/undef_reflink_title/_build/page.html ================================================ page
================================================ FILE: urubu/tests/undef_reflink_title/_layouts/_base.html ================================================ {{this.title}} {% set bootstrap = "3.1.1" %} {% if site.bootstrap %} {% set bootstrap = site.bootstrap %} {% endif %} {% if site.bootswatch %} {% set theme_path = "bootswatch/"+ bootstrap + '/' + site.bootswatch %} {% else %} {% set theme_path = "bootstrap/" + bootstrap + "/css" %} {% endif %} {% set url_prefix = '' %} {% if site.baseurl %} {% set url_prefix = '/' + site.baseurl %} {% endif %} {% set navbar_style = "navbar-default" %} {% if site.navbar_inverse %} {% set navbar_style = "navbar-inverse" %} {% endif %} {% set navbar_right_items = 2 %} {% if site.navbar_right_items %} {% set navbar_right_items = site.navbar_right_items %} {% endif %} {% block body %} {% endblock %} ================================================ FILE: urubu/tests/undef_reflink_title/_layouts/page.html ================================================ {% extends "_base.html" %} {% block body %}
{% block content %}
{{this.body}}
{% endblock %}
{% block sidebar %} {% if this.toc %} {% endif %} {% endblock %}
{% if this.pager %} {% endif %}
{% endblock %} ================================================ FILE: urubu/tests/undef_reflink_title/_site.yml ================================================ brand: Urubu bootswatch: null navbar_inverse: false bootstrap: 3.3.4 ignore_patterns: ['*.py', 'README.md'] reflinks: jandecaluwe: url: ttp://www.jandecaluwe.com title: Jan Decaluwe myhdl_site: url: http://www.myhdl.org dev_myhdl_site: url: http://dev.myhdl.org title: MyHDL development website content_license: url: http://creativecommons.org/licenses/by-sa/3.0/ title: CC-BY-SA License software_license: url: http://www.gnu.org/licenses/agpl-3.0.txt title: GNU Affero General Public License bitbucket: url: http://www.bitbucket.com title: Bitbucket github: url: http://www.github.com title: GitHub markdown: url: http://daringfireball.net/projects/markdown/ title: Markdown markdown_extra: url: http://pythonhosted.org/Markdown/extensions/extra.html title: Markdown Extra python_markdown: url: http://pythonhosted.org/Markdown/ title: Python-Markdown pygments: url: http://pygments.org title: Pygments jinja2: url: http://jinja.pocoo.org title: Jinja2 bootstrap: url: http://getbootstrap.com title: Bootstrap bootswatch: url: http://bootswatch.com title: Bootswatch pyyaml: url: http://pyyaml.org title: PyYAML jekyll: url: http://jekyllrb.com title: Jekyll pelican: url: http://getpelican.com title: Pelican virtualenv: url: http://www.virtualenv.org/en/latest/virtualenv.html title: virtualenv urubu_repo: url: https://github.com/jandecaluwe/urubu title: Urubu repo tables: url: http://pythonhosted.org/Markdown/extensions/tables.html title: Tables abbrev: url: http://pythonhosted.org/Markdown/extensions/abbreviations.html title: Abbrevations attr_list: url: http://pythonhosted.org/Markdown/extensions/attr_list.html title: Attribute lists def_list: url: http://pythonhosted.org/Markdown/extensions/definition_lists.html title: Definition Lists fenced_code: url: http://pythonhosted.org/Markdown/extensions/fenced_code_blocks.html title: Fenced Code Blocks markdown_checklist: url: https://github.com/FND/markdown-checklist title: GitHub style Task Lists code_hilite: url: http://pythonhosted.org/Markdown/extensions/code_hilite.html title: CodeHilite urubu-quickstart: url: http://urubu-quickstart.jandecaluwe.com title: Urubu Quickstart ================================================ FILE: urubu/tests/undef_reflink_title/index.md ================================================ --- title: test layout: page content: - page --- ================================================ FILE: urubu/tests/undef_reflink_title/page.md ================================================ --- title: page layout: page --- ================================================ FILE: urubu/tests/undef_reflink_url/_build/index.html ================================================ test
================================================ FILE: urubu/tests/undef_reflink_url/_build/page.html ================================================ page
================================================ FILE: urubu/tests/undef_reflink_url/_layouts/_base.html ================================================ {{this.title}} {% set bootstrap = "3.1.1" %} {% if site.bootstrap %} {% set bootstrap = site.bootstrap %} {% endif %} {% if site.bootswatch %} {% set theme_path = "bootswatch/"+ bootstrap + '/' + site.bootswatch %} {% else %} {% set theme_path = "bootstrap/" + bootstrap + "/css" %} {% endif %} {% set url_prefix = '' %} {% if site.baseurl %} {% set url_prefix = '/' + site.baseurl %} {% endif %} {% set navbar_style = "navbar-default" %} {% if site.navbar_inverse %} {% set navbar_style = "navbar-inverse" %} {% endif %} {% set navbar_right_items = 2 %} {% if site.navbar_right_items %} {% set navbar_right_items = site.navbar_right_items %} {% endif %} {% block body %} {% endblock %} ================================================ FILE: urubu/tests/undef_reflink_url/_layouts/page.html ================================================ {% extends "_base.html" %} {% block body %}
{% block content %}
{{this.body}}
{% endblock %}
{% block sidebar %} {% if this.toc %} {% endif %} {% endblock %}
{% if this.pager %} {% endif %}
{% endblock %} ================================================ FILE: urubu/tests/undef_reflink_url/_site.yml ================================================ brand: Urubu bootswatch: null navbar_inverse: false bootstrap: 3.3.4 ignore_patterns: ['*.py', 'README.md'] reflinks: jandecaluwe: url: ttp://www.jandecaluwe.com title: Jan Decaluwe myhdl_site: title: MyHDL website dev_myhdl_site: url: http://dev.myhdl.org title: MyHDL development website content_license: url: http://creativecommons.org/licenses/by-sa/3.0/ title: CC-BY-SA License software_license: url: http://www.gnu.org/licenses/agpl-3.0.txt title: GNU Affero General Public License bitbucket: url: http://www.bitbucket.com title: Bitbucket github: url: http://www.github.com title: GitHub markdown: url: http://daringfireball.net/projects/markdown/ title: Markdown markdown_extra: url: http://pythonhosted.org/Markdown/extensions/extra.html title: Markdown Extra python_markdown: url: http://pythonhosted.org/Markdown/ title: Python-Markdown pygments: url: http://pygments.org title: Pygments jinja2: url: http://jinja.pocoo.org title: Jinja2 bootstrap: url: http://getbootstrap.com title: Bootstrap bootswatch: url: http://bootswatch.com title: Bootswatch pyyaml: url: http://pyyaml.org title: PyYAML jekyll: url: http://jekyllrb.com title: Jekyll pelican: url: http://getpelican.com title: Pelican virtualenv: url: http://www.virtualenv.org/en/latest/virtualenv.html title: virtualenv urubu_repo: url: https://github.com/jandecaluwe/urubu title: Urubu repo tables: url: http://pythonhosted.org/Markdown/extensions/tables.html title: Tables abbrev: url: http://pythonhosted.org/Markdown/extensions/abbreviations.html title: Abbrevations attr_list: url: http://pythonhosted.org/Markdown/extensions/attr_list.html title: Attribute lists def_list: url: http://pythonhosted.org/Markdown/extensions/definition_lists.html title: Definition Lists fenced_code: url: http://pythonhosted.org/Markdown/extensions/fenced_code_blocks.html title: Fenced Code Blocks markdown_checklist: url: https://github.com/FND/markdown-checklist title: GitHub style Task Lists code_hilite: url: http://pythonhosted.org/Markdown/extensions/code_hilite.html title: CodeHilite urubu-quickstart: url: http://urubu-quickstart.jandecaluwe.com title: Urubu Quickstart ================================================ FILE: urubu/tests/undef_reflink_url/index.md ================================================ --- title: test layout: page content: - page --- ================================================ FILE: urubu/tests/undef_reflink_url/page.md ================================================ --- title: page layout: page --- ================================================ FILE: urubu/tests/undef_tag_layout/_build/index.html ================================================ test
================================================ FILE: urubu/tests/undef_tag_layout/_build/page.html ================================================ page
================================================ FILE: urubu/tests/undef_tag_layout/_layouts/_base.html ================================================ {{this.title}} {% set bootstrap = "3.1.1" %} {% if site.bootstrap %} {% set bootstrap = site.bootstrap %} {% endif %} {% if site.bootswatch %} {% set theme_path = "bootswatch/"+ bootstrap + '/' + site.bootswatch %} {% else %} {% set theme_path = "bootstrap/" + bootstrap + "/css" %} {% endif %} {% set url_prefix = '' %} {% if site.baseurl %} {% set url_prefix = '/' + site.baseurl %} {% endif %} {% set navbar_style = "navbar-default" %} {% if site.navbar_inverse %} {% set navbar_style = "navbar-inverse" %} {% endif %} {% set navbar_right_items = 2 %} {% if site.navbar_right_items %} {% set navbar_right_items = site.navbar_right_items %} {% endif %} {% block body %} {% endblock %} ================================================ FILE: urubu/tests/undef_tag_layout/_layouts/page.html ================================================ {% extends "_base.html" %} {% block body %}
{% block content %}
{{this.body}}
{% endblock %}
{% block sidebar %} {% if this.toc %} {% endif %} {% endblock %}
{% if this.pager %} {% endif %}
{% endblock %} ================================================ FILE: urubu/tests/undef_tag_layout/_site.yml ================================================ brand: Urubu bootswatch: null navbar_inverse: false bootstrap: 3.3.4 ignore_patterns: ['*.py', 'README.md'] reflinks: jandecaluwe: url: ttp://www.jandecaluwe.com title: Jan Decaluwe myhdl_site: url: http://www.myhdl.org title: MyHDL website dev_myhdl_site: url: http://dev.myhdl.org title: MyHDL development website content_license: url: http://creativecommons.org/licenses/by-sa/3.0/ title: CC-BY-SA License software_license: url: http://www.gnu.org/licenses/agpl-3.0.txt title: GNU Affero General Public License bitbucket: url: http://www.bitbucket.com title: Bitbucket github: url: http://www.github.com title: GitHub markdown: url: http://daringfireball.net/projects/markdown/ title: Markdown markdown_extra: url: http://pythonhosted.org/Markdown/extensions/extra.html title: Markdown Extra python_markdown: url: http://pythonhosted.org/Markdown/ title: Python-Markdown pygments: url: http://pygments.org title: Pygments jinja2: url: http://jinja.pocoo.org title: Jinja2 bootstrap: url: http://getbootstrap.com title: Bootstrap bootswatch: url: http://bootswatch.com title: Bootswatch pyyaml: url: http://pyyaml.org title: PyYAML jekyll: url: http://jekyllrb.com title: Jekyll pelican: url: http://getpelican.com title: Pelican virtualenv: url: http://www.virtualenv.org/en/latest/virtualenv.html title: virtualenv urubu_repo: url: https://github.com/jandecaluwe/urubu title: Urubu repo tables: url: http://pythonhosted.org/Markdown/extensions/tables.html title: Tables abbrev: url: http://pythonhosted.org/Markdown/extensions/abbreviations.html title: Abbrevations attr_list: url: http://pythonhosted.org/Markdown/extensions/attr_list.html title: Attribute lists def_list: url: http://pythonhosted.org/Markdown/extensions/definition_lists.html title: Definition Lists fenced_code: url: http://pythonhosted.org/Markdown/extensions/fenced_code_blocks.html title: Fenced Code Blocks markdown_checklist: url: https://github.com/FND/markdown-checklist title: GitHub style Task Lists code_hilite: url: http://pythonhosted.org/Markdown/extensions/code_hilite.html title: CodeHilite urubu-quickstart: url: http://urubu-quickstart.jandecaluwe.com title: Urubu Quickstart ================================================ FILE: urubu/tests/undef_tag_layout/index.md ================================================ --- title: test layout: page content: - page --- ================================================ FILE: urubu/tests/undef_tag_layout/page.md ================================================ --- title: page layout: page tags: tag ---