├── MANIFEST.in ├── docs ├── requirements.txt ├── conf.py ├── about.rst ├── index.rst ├── installation.rst ├── tabs.rst ├── columns.rst ├── toggle.rst └── example-all.rst ├── setup.cfg ├── .gitignore ├── Dockerfile.centos ├── sphinxcontrib ├── __init__.py ├── contentui.js ├── contentui.css └── contentui.py ├── CHANGES.rst ├── tox.ini ├── LICENSE ├── setup.py ├── README.rst └── Makefile /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.* 2 | include LICENSE 3 | include CHANGES.* 4 | global-include *.js *.css 5 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | -e git://github.com/ulrobix/sphinxcontrib-contentui.git#egg=sphinxcontrib-contentui 2 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [egg_info] 2 | tag_build = 3 | tag_date = false 4 | 5 | [aliases] 6 | release = egg_info -RDb '' 7 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | master_doc = 'index' 2 | project = 'Contentui extension for Sphinx' 3 | extensions = ['sphinxcontrib.contentui'] -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *egg-info 2 | *.pyc 3 | .idea 4 | .installed.cfg 5 | .DS_Store 6 | docs/_build/* 7 | include/ 8 | lib/ 9 | lib64 10 | pip-selfcheck.json 11 | dist/ 12 | html/ 13 | -------------------------------------------------------------------------------- /docs/about.rst: -------------------------------------------------------------------------------- 1 | About 2 | ===== 3 | 4 | This is a simple Sphinx extension that is rendered as HTML widgets: 5 | 6 | - :ref:`content-tabs` 7 | - :ref:`column-content` 8 | - :ref:`toggle-header` 9 | -------------------------------------------------------------------------------- /Dockerfile.centos: -------------------------------------------------------------------------------- 1 | from centos/python-36-centos7 2 | USER root 3 | RUN pip install -U virtualenv 4 | COPY Makefile /opt/app-root/src/Makefile 5 | ARG UID 6 | ARG VENV_DIR 7 | USER $UID 8 | RUN make VENV_DIR=/opt/app-root/src/$VENV_DIR /opt/app-root/src/$VENV_DIR 9 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | ============================== 2 | Contentui extension for Sphinx 3 | ============================== 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | 8 | about 9 | installation 10 | tabs 11 | columns 12 | toggle 13 | example-all 14 | -------------------------------------------------------------------------------- /docs/installation.rst: -------------------------------------------------------------------------------- 1 | Installation 2 | ------------ 3 | 4 | .. code-block:: bash 5 | 6 | $ pip install sphinxcontrib-contentui 7 | 8 | 9 | Enabling the extension in Sphinx 10 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11 | 12 | Just add sphinxcontrib.contentui to the list of extensions in the **conf.py** file. For example: 13 | 14 | .. code-block:: bash 15 | 16 | extensions = ['sphinxcontrib.contentui'] -------------------------------------------------------------------------------- /sphinxcontrib/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | sphinxcontrib 4 | ~~~~~~~~~~~~~ 5 | 6 | This package is a namespace package that contains all extensions 7 | distributed in the ``sphinx-contrib`` distribution. 8 | 9 | :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS. 10 | :license: BSD, see LICENSE for details. 11 | """ 12 | 13 | __import__('pkg_resources').declare_namespace(__name__) 14 | 15 | -------------------------------------------------------------------------------- /CHANGES.rst: -------------------------------------------------------------------------------- 1 | Changelog 2 | ========= 3 | 4 | 0.2.5 (2020-04-18) 5 | ------------------ 6 | 7 | - Update deprecated js and css Sphinx commands 8 | 9 | 10 | 0.2.4 (2019-04-13) 11 | ------------------ 12 | 13 | - fixed toggle-header on Centos 14 | 15 | 16 | 0.2.3 (2019-04-12) 17 | ------------------ 18 | 19 | - fixed logging for sphinx 2 20 | 21 | 22 | 0.2.2 (2017-03-23) 23 | ------------------ 24 | 25 | - fixed css 26 | 27 | 0.2.1 (2017-02-26) 28 | ------------------ 29 | 30 | - fixed docs 31 | 32 | 0.2.0 (2017-02-25) 33 | ------------------ 34 | 35 | - initial fork 36 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | ## configuration for tox 2 | 3 | ## tox automates running certain tasks within virtualenvs. The following 4 | ## tox configuration outlines a basic setup for running unit tests and 5 | ## building sphinx docs in separate virtual environments. Give it a try! 6 | 7 | [tox] 8 | envlist=python,doc 9 | 10 | # test running 11 | [testenv:python] 12 | deps= 13 | ## if you use nose for test running 14 | # nose 15 | ## if you use py.test for test running 16 | # pytest 17 | commands= 18 | ## run tests with py.test 19 | # py.test [] 20 | ## run tests with nose 21 | # nose 22 | 23 | [testenv:doc] 24 | deps= 25 | sphinx 26 | # add all Sphinx extensions and other dependencies required to build your docs 27 | commands= 28 | ## test links 29 | # sphinx-build -W -b linkcheck -d {envtmpdir}/doctrees doc {envtmpdir}/linkcheck 30 | ## test html output 31 | # sphinx-build -W -b html -d {envtmpdir}/doctrees doc {envtmpdir}/html 32 | 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Robert 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from setuptools import setup, find_packages 4 | 5 | long_desc = ''' 6 | This package contains the contentui Sphinx extension. 7 | ''' 8 | 9 | requires = ['Sphinx>=2.0'] 10 | 11 | setup( 12 | name='sphinxcontrib-contentui', 13 | version='0.2.5', 14 | url='https://github.com/ulrobix/sphinxcontrib-contentui', 15 | download_url='http://pypi.python.org/pypi/sphinxcontrib-contentui', 16 | license='BSD', 17 | author='Robert Khaliullov', 18 | author_email='ulrobix@gmail.com', 19 | description='Sphinx "contentui" extension', 20 | long_description=long_desc, 21 | zip_safe=False, 22 | classifiers=[ 23 | 'Development Status :: 4 - Beta', 24 | 'Environment :: Console', 25 | 'Environment :: Web Environment', 26 | 'Intended Audience :: Developers', 27 | 'License :: OSI Approved :: BSD License', 28 | 'Operating System :: OS Independent', 29 | 'Programming Language :: Python', 30 | 'Topic :: Documentation', 31 | 'Topic :: Utilities', 32 | ], 33 | platforms='any', 34 | packages=find_packages(), 35 | include_package_data=True, 36 | install_requires=requires, 37 | namespace_packages=['sphinxcontrib'], 38 | ) 39 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | .. -*- restructuredtext -*- 2 | 3 | ============================== 4 | Contentui extension for Sphinx 5 | ============================== 6 | 7 | This is a modified fork of Serge Domkowski's `examplecode extension 8 | `_ 9 | for Sphinx. 10 | 11 | 12 | About 13 | ===== 14 | 15 | This is a simple extension that is rendered as HTML widgets: 16 | 17 | - `Content tab `_ 18 | - `Column content `_ 19 | - `Toggle header `_ 20 | 21 | 22 | Example 23 | ------- 24 | 25 | `All-in-One Example `_ 26 | 27 | 28 | Installation 29 | ------------ 30 | 31 | .. code-block:: bash 32 | 33 | $ pip install sphinxcontrib-contentui 34 | 35 | 36 | Enabling the extension in Sphinx 37 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 38 | 39 | Just add sphinxcontrib.contentui to the list of extensions in the **conf.py** file. For example: 40 | 41 | .. code-block:: bash 42 | 43 | extensions = ['sphinxcontrib.contentui'] 44 | 45 | 46 | Documentation 47 | ------------- 48 | 49 | Full documentation for end users can be found in the "docs" folder. 50 | 51 | It is also available online on `Read The Docs `_ 52 | 53 | 54 | .. Links: 55 | .. _Sphinx: http://sphinx.pocoo.org/` 56 | 57 | 58 | License 59 | ------- 60 | 61 | sphinxcontrib-contentui is licensed under the MIT License 62 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) 2 | BUILD_DIR := $(patsubst %/,%,$(dir $(MKFILE_PATH))) 3 | 4 | # local 5 | .PHONY: dist push html clear install uninstall 6 | 7 | PYTHON := $(shell which python3.6 2>/dev/null || echo python3) 8 | VIRTUALENV := $(shell which virtualenv 2>/dev/null || echo virtualenv) 9 | VENV_DIR := $(BUILD_DIR)/venv 10 | HTML_DIR := $(BUILD_DIR)/html 11 | 12 | $(VENV_DIR): 13 | $(PYTHON) $(VIRTUALENV) -p $(PYTHON) $(VENV_DIR) 14 | 15 | dist: $(VENV_DIR) 16 | rm -rf $(BUILD_DIR)/dist 17 | $(VENV_DIR)/bin/python setup.py bdist_wheel 18 | 19 | push: $(VENV_DIR) 20 | $(VENV_DIR)/bin/pip install twine 21 | $(VENV_DIR)/bin/twine upload $(BUILD_DIR)/dist/* 22 | 23 | install: $(VENV_DIR) 24 | $(VENV_DIR)/bin/pip install $(BUILD_DIR)/dist/$(shell ls $(BUILD_DIR)/dist | head -1) 25 | 26 | uninstall: $(VENV_DIR) 27 | $(VENV_DIR)/bin/pip uninstall -y sphinxcontrib-contentui 28 | 29 | html: dist uninstall install 30 | rm -rf $(HTML_DIR) 31 | $(VENV_DIR)/bin/sphinx-build -b html $(BUILD_DIR)/docs $(HTML_DIR) 32 | 33 | clear: 34 | rm -rf $(VENV_DIR) $(HTML_DIR) $(BUILD_DIR)/dist $(BUILD_DIR)/build 35 | $(DOCKER) rmi $(DOCKER_IMAGE) 36 | 37 | # docker 38 | .PHONY: docker-dist docker-push docker-build docker-html 39 | 40 | DOCKER := $(shell which docker 2>/dev/null || echo docker) 41 | UID := $(shell id -u) 42 | BUILD_OS := centos 43 | DOCKER_IMAGE := build_contentui.$(BUILD_OS) 44 | DOCKER_VENV := venv 45 | 46 | docker-build: 47 | $(DOCKER) build -f Dockerfile.$(BUILD_OS) --build-arg UID=$(UID) --build-arg VENV_DIR=$(DOCKER_VENV) -t $(DOCKER_IMAGE) . 48 | 49 | docker-dist: docker-build 50 | $(DOCKER) run -it --rm -u $(UID) -v $(BUILD_DIR):/opt/app-root/src $(DOCKER_IMAGE) make VENV_DIR=$(DOCKER_VENV) dist 51 | 52 | docker-push: docker-build 53 | $(DOCKER) run -it --rm -u $(UID) -v $(BUILD_DIR):/opt/app-root/src $(DOCKER_IMAGE) make VENV_DIR=$(DOCKER_VENV) push 54 | 55 | docker-html: docker-build 56 | $(DOCKER) run -it --rm -u $(UID) -v $(BUILD_DIR):/opt/app-root/src $(DOCKER_IMAGE) make VENV_DIR=$(DOCKER_VENV) html 57 | -------------------------------------------------------------------------------- /sphinxcontrib/contentui.js: -------------------------------------------------------------------------------- 1 | 2 | $(function() { 3 | /* 4 | * Right column logic 5 | */ 6 | if ($(".right-col").length) { 7 | $(".right-col").after('
'); 8 | $(".right-col").parents('body').addClass('with-columns'); 9 | } 10 | 11 | /** 12 | * Toggle logic 13 | */ 14 | $('.toggle-content').hide() 15 | $('.toggle-header').click(function () { 16 | $(this).toggleClass("open"); 17 | $(this).next('.toggle-content').toggle('400'); 18 | }) 19 | 20 | /** 21 | * Dynamic multiple content block. 22 | */ 23 | var top_sel = {} 24 | 25 | $('div.content-tabs').each(function() { 26 | var contenttab_sel = $('
    ', { class: "contenttab-selector" }); 27 | var i = 0; 28 | 29 | if ($(this).hasClass('right-col')){ 30 | contenttab_sel.addClass('in-right-col'); 31 | } 32 | 33 | $('.tab-content', this).each(function() { 34 | var sel_item = $('
  • ', { 35 | class: $(this).attr('id'), 36 | text: $(this).find('.tab-title').text() 37 | }); 38 | $(this).find('.tab-title').remove(); 39 | if (i++) { 40 | $(this).hide(); 41 | } else { 42 | sel_item.addClass('selected'); 43 | } 44 | contenttab_sel.append(sel_item); 45 | $(this).addClass('contenttab'); 46 | }); 47 | 48 | $('.tab-content', this).eq(0).before(contenttab_sel); 49 | contenttab_sel = null; 50 | i = null; 51 | }); 52 | 53 | 54 | $('.contenttab-selector li').click(function(evt) { 55 | evt.preventDefault(); 56 | 57 | if ($(this).parents('.in-right-col').length){ 58 | var tabsblock = $('.right-col'); 59 | }else{ 60 | var tabsblock = $(this).parents('.content-tabs'); 61 | } 62 | 63 | var sel_class = $(this).attr('class'); 64 | $('div.contenttab',tabsblock).hide(); 65 | $('div#' + sel_class,tabsblock).show(); 66 | 67 | $('ul.contenttab-selector li', tabsblock).removeClass('selected'); 68 | $('ul.contenttab-selector li.' + sel_class, tabsblock).addClass('selected'); 69 | 70 | sel_class = null; 71 | }); 72 | 73 | }); 74 | 75 | -------------------------------------------------------------------------------- /docs/tabs.rst: -------------------------------------------------------------------------------- 1 | .. _content-tabs: 2 | 3 | Content tabs 4 | ------------ 5 | 6 | .. rst:directive:: .. content-tabs:: class 7 | 8 | or: 9 | 10 | .. rst:directive:: .. container:: content-tabs class 11 | 12 | "content-tabs" directive creates a block with content tabs. 13 | Content of only one tab will be shown at the same time. 14 | Content switches with click on corresponding tab's caption. 15 | Click on caption of `tab-container`'s caption with the same `name` attribute 16 | activates all tabs with the same `name` in all `content-tab` blocks with the same 17 | attribute `class`. 18 | 19 | Special class :ref:`right-col ` fixates the "content-tabs" 20 | menu in the upper right position, see :ref:`example-all`. 21 | 22 | .. rst:directive:: .. tab-container:: name 23 | 24 | "tab-container" directive creates a content tab. Tab's caption is set by 25 | `title` option. To switch tabs synchronously the `name` attribute should match 26 | with "tab-container" from another blocks. 27 | 28 | Full example:: 29 | 30 | .. content-tabs:: 31 | 32 | .. tab-container:: tab1 33 | :title: Tab title one 34 | 35 | Content for tab one 36 | 37 | .. tab-container:: tab2 38 | :title: Tab title two 39 | 40 | Content for tab two 41 | 42 | 43 | will be rendered like this: 44 | 45 | .. content-tabs:: 46 | 47 | .. tab-container:: tab1 48 | :title: Tab title one 49 | 50 | Content for tab one 51 | 52 | .. tab-container:: tab2 53 | :title: Tab title two 54 | 55 | Content for tab two 56 | 57 | Generated HTML code: 58 | 59 | .. code-block:: html 60 | 61 |
    62 |
      63 |
    • Tab title one
    • 64 |
    • Tab title two
    • 65 |
    66 |
    67 |

    Content for tab one

    68 |
    69 | 72 |
    73 | 74 | More examples 75 | ~~~~~~~~~~~~~ 76 | 77 | .. content-tabs:: 78 | 79 | .. tab-container:: python 80 | :title: Python 81 | 82 | .. rubric:: Definition 83 | 84 | .. code-block:: python 85 | 86 | my_api.signin() 87 | 88 | .. rubric:: Example request 89 | 90 | .. code-block:: python 91 | 92 | import my_api 93 | my_api.signin('username', 'password') 94 | 95 | 96 | .. tab-container:: php 97 | :title: PHP 98 | 99 | .. rubric:: Definition 100 | 101 | .. code-block:: php 102 | 103 | MyApi::signin(); 104 | 105 | .. rubric:: Example request 106 | 107 | .. code-block:: php 108 | 109 | include 'my-api.php'; 110 | MyApi::signin('username', 'password'); 111 | -------------------------------------------------------------------------------- /docs/columns.rst: -------------------------------------------------------------------------------- 1 | .. _column-content: 2 | 3 | Column content 4 | -------------- 5 | 6 | .. container:: left-col 7 | 8 | Use `container` or another directive with classes `left-col` / `right-col` to 9 | display the content in two columns. 10 | 11 | .. note:: Supported only **sphinx_rtd_theme**. The right column displays only the windows width more than 1300 px. 12 | 13 | Full example:: 14 | 15 | .. container:: left-col 16 | 17 | Left column text 18 | 19 | .. container:: left-col 20 | 21 | Right column text 22 | 23 | More examples 24 | ~~~~~~~~~~~~~ 25 | 26 | .. container:: left-col 27 | 28 | .. rubric:: Content in left column 29 | 30 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor 31 | incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis 32 | nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. 33 | Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu 34 | fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in 35 | culpa qui officia deserunt mollit anim id est laborum 36 | 37 | .. container:: right-col 38 | 39 | .. rubric:: Content in right column 40 | 41 | Sed ut perspiciatis, unde omnis iste natus error sit voluptatem 42 | accusantium doloremque laudantium, totam rem aperiam eaque ipsa, quae 43 | ab illo inventore veritatis et quasi architecto beatae vitae dicta 44 | sunt, explicabo. Nemo enim ipsam voluptatem, quia voluptas sit, 45 | aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos, 46 | qui ratione voluptatem sequi nesciunt, neque porro quisquam est, qui 47 | dolorem ipsum, quia dolor sit, amet, consectetur, adipisci velit, sed 48 | quia non numquam eius modi tempora incidunt, ut labore et dolore magnam 49 | aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum 50 | exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex 51 | ea commodi consequatur? Quis autem vel eum iure reprehenderit, qui in 52 | ea voluptate velit esse, quam nihil molestiae consequatur, vel illum, 53 | qui dolorem eum fugiat, quo voluptas nulla pariatur? At vero eos et 54 | accusamus et iusto odio dignissimos ducimus, qui blanditiis praesentium 55 | voluptatum deleniti atque corrupti, quos dolores et quas molestias 56 | excepturi sint, obcaecati cupiditate non provident, similique sunt in 57 | culpa, qui officia deserunt mollitia animi, id est laborum et dolorum 58 | fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam 59 | libero tempore, cum soluta nobis est eligendi optio, cumque nihil 60 | impedit, quo minus id, quod maxime placeat, facere possimus, omnis 61 | voluptas assumenda est, omnis dolor repellendus. Temporibus autem 62 | quibusdam et aut officiis debitis aut rerum necessitatibus saepe 63 | eveniet, ut et voluptates repudiandae sint et molestiae non recusandae. 64 | Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis 65 | voluptatibus maiores alias consequatur aut perferendis doloribus 66 | asperiores repellat. 67 | 68 | -------------------------------------------------------------------------------- /sphinxcontrib/contentui.css: -------------------------------------------------------------------------------- 1 | /* 2 | * right column for sphinx_rtd_theme 3 | */ 4 | .clear { 5 | clear: both; 6 | } 7 | 8 | @media screen and (min-width: 1300px) { 9 | .wy-nav-content { 10 | max-width: none; 11 | } 12 | 13 | .with-columns .wy-nav-content { 14 | background: linear-gradient(90deg, #fcfcfc 52%, #eeeeee 52%); 15 | } 16 | 17 | .with-columns .wy-nav-content .wy-breadcrumbs , 18 | .with-columns .section > h1, 19 | .with-columns .section > h2, 20 | .with-columns .section > h3, 21 | .with-columns footer { 22 | width: 50%; 23 | } 24 | 25 | .with-columns .section { 26 | clear: both; 27 | } 28 | 29 | .left-col.container { 30 | float: left; 31 | width: 50%; 32 | margin-right: 4%; 33 | } 34 | 35 | .right-col.container { 36 | float: left; 37 | width: 45%; 38 | } 39 | 40 | /* 41 | * tab selector fixed in top 42 | */ 43 | .with-columns .contenttab-selector.in-right-col { 44 | display: block; 45 | position: fixed; 46 | top: 0; 47 | right: 0; 48 | width: calc(48% - 144px); 49 | background: #444; 50 | padding: 5px 10px; 51 | } 52 | 53 | } 54 | 55 | /** 56 | * 57 | */ 58 | .toggle-tab { 59 | margin-bottom: 40px; 60 | } 61 | 62 | .toggle-header { 63 | display: block; 64 | clear: both; 65 | cursor: pointer; 66 | } 67 | .toggle-header p {display: inline; } 68 | .toggle-header strong {color: #2980b9 } 69 | 70 | .toggle-header:after { 71 | content: " ▼"; 72 | } 73 | 74 | .toggle-header.open:after { 75 | content: " ▲"; 76 | } 77 | 78 | .toggle-content { 79 | display: none; 80 | margin-bottom: 20px; 81 | } 82 | 83 | /* 84 | * tab menu 85 | */ 86 | ul.contenttab-selector { 87 | display:block; 88 | list-style-type: none; 89 | margin: 0 0 10px; 90 | padding: 0; 91 | line-height: normal; 92 | overflow: auto; 93 | } 94 | ul.contenttab-selector li { 95 | display: block; 96 | cursor: pointer; 97 | font-weight: bold; 98 | margin: 0 5px 0 0; 99 | padding: 5px 10px; 100 | float: left; 101 | background-color: #999; 102 | color: #fff; 103 | -moz-border-radius: 5px; 104 | -webkit-border-radius: 5px; 105 | border-radius: 5px; 106 | -khtml-border-radius: 5px; 107 | } 108 | .rst-content .section ul.contenttab-selector, 109 | .rst-content .toctree-wrapper ul.contenttab-selector, 110 | article ul.contenttab-selector{ 111 | line-height: normal; 112 | margin: 0 0 10px; 113 | } 114 | .rst-content .section ul.contenttab-selector li, 115 | .rst-content .toctree-wrapper ul.contenttab-selector li, 116 | article ul.contenttab-selector li{ 117 | margin-left: 0; 118 | } 119 | ul.contenttab-selector li:hover { 120 | background-color: #777; 121 | } 122 | ul.contenttab-selector li.selected { 123 | background-color: #2980b9; 124 | } 125 | ul.contenttab-selector li.selected:hover { 126 | background-color: #333; 127 | } 128 | .content-tabs { 129 | margin: 10px 0 20px 0; 130 | } 131 | .tab-content { 132 | clear: both; 133 | } 134 | -------------------------------------------------------------------------------- /docs/toggle.rst: -------------------------------------------------------------------------------- 1 | .. _toggle-header: 2 | 3 | Toggle headers 4 | -------------- 5 | 6 | .. rst:directive:: .. toggle-header:: class 7 | 8 | "toggle-header" directive creates a block with a visible heading for the 9 | hidden content. The heading can be clicked to view/hide the hidden content. 10 | Optional attribute `class` adds css class for hidden content. 11 | Required option `header` sets text of the heading of the hidden content. 12 | 13 | Full example:: 14 | 15 | .. toggle-header:: 16 | :header: Example 1 **Show/Hide Code** 17 | 18 | Content for header 19 | 20 | 21 | will be rendered like this: 22 | 23 | .. toggle-header:: 24 | :header: Example 1 **Show/Hide Code** 25 | 26 | Content for header 27 | 28 | Generated HTML code: 29 | 30 | .. code-block:: html 31 | 32 |
    33 |

    Example Show/Hide Code

    34 |
    35 |
    36 | Content for header 37 |
    38 | 39 | More examples 40 | ~~~~~~~~~~~~~ 41 | 42 | .. toggle-header:: 43 | :header: Example 1 **Show/Hide Code** 44 | 45 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor 46 | incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis 47 | nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. 48 | Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu 49 | fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in 50 | culpa qui officia deserunt mollit anim id est laborum 51 | 52 | 53 | .. toggle-header:: rubric 54 | :header: Example 2 55 | 56 | Sed ut perspiciatis, unde omnis iste natus error sit voluptatem 57 | accusantium doloremque laudantium, totam rem aperiam eaque ipsa, quae 58 | ab illo inventore veritatis et quasi architecto beatae vitae dicta 59 | sunt, explicabo. Nemo enim ipsam voluptatem, quia voluptas sit, 60 | aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos, 61 | qui ratione voluptatem sequi nesciunt, neque porro quisquam est, qui 62 | dolorem ipsum, quia dolor sit, amet, consectetur, adipisci velit, sed 63 | quia non numquam eius modi tempora incidunt, ut labore et dolore magnam 64 | aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum 65 | exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex 66 | ea commodi consequatur? Quis autem vel eum iure reprehenderit, qui in 67 | ea voluptate velit esse, quam nihil molestiae consequatur, vel illum, 68 | qui dolorem eum fugiat, quo voluptas nulla pariatur? At vero eos et 69 | accusamus et iusto odio dignissimos ducimus, qui blanditiis praesentium 70 | voluptatum deleniti atque corrupti, quos dolores et quas molestias 71 | excepturi sint, obcaecati cupiditate non provident, similique sunt in 72 | culpa, qui officia deserunt mollitia animi, id est laborum et dolorum 73 | fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam 74 | libero tempore, cum soluta nobis est eligendi optio, cumque nihil 75 | impedit, quo minus id, quod maxime placeat, facere possimus, omnis 76 | voluptas assumenda est, omnis dolor repellendus. Temporibus autem 77 | quibusdam et aut officiis debitis aut rerum necessitatibus saepe 78 | eveniet, ut et voluptates repudiandae sint et molestiae non recusandae. 79 | Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis 80 | voluptatibus maiores alias consequatur aut perferendis doloribus 81 | asperiores repellat. 82 | -------------------------------------------------------------------------------- /sphinxcontrib/contentui.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Content ui specs 4 | ================= 5 | """ 6 | import os 7 | from docutils.parsers.rst import Directive, directives 8 | from docutils import nodes 9 | from docutils.statemachine import StringList 10 | from sphinx.util.osutil import copyfile 11 | from sphinx.util import logging 12 | 13 | 14 | CSS_FILE = 'contentui.css' 15 | JS_FILE = 'contentui.js' 16 | 17 | 18 | class ContentTabsDirective(Directive): 19 | """ 20 | It's container directive with content-tabs class 21 | """ 22 | 23 | has_content = True 24 | optional_arguments = 1 25 | 26 | def run(self): 27 | self.assert_has_content() 28 | text = '\n'.join(self.content) 29 | node = nodes.container(text) 30 | node['classes'].append('content-tabs') 31 | 32 | if self.arguments and self.arguments[0]: 33 | node['classes'].append(self.arguments[0]) 34 | 35 | self.add_name(node) 36 | self.state.nested_parse(self.content, self.content_offset, node) 37 | return [node] 38 | 39 | 40 | class ContentTabsContainerDirective(Directive): 41 | has_content = True 42 | option_spec = {'title': directives.unchanged} 43 | required_arguments = 1 44 | 45 | def run(self): 46 | self.assert_has_content() 47 | text = '\n'.join(self.content) 48 | node = nodes.container(text) 49 | node['ids'].append('tab-%s' % self.arguments[0]) 50 | node['classes'].append('tab-content') 51 | 52 | par = nodes.paragraph(text=self.options["title"]) 53 | par['classes'].append('tab-title') 54 | node += par 55 | 56 | self.add_name(node) 57 | self.state.nested_parse(self.content, self.content_offset, node) 58 | 59 | return [node] 60 | 61 | 62 | class ToggleDirective(Directive): 63 | has_content = True 64 | option_spec = {'header': directives.unchanged} 65 | optional_arguments = 1 66 | 67 | def run(self): 68 | node = nodes.container() 69 | node['classes'].append('toggle-content') 70 | 71 | par = nodes.container() 72 | par['classes'].append('toggle-header') 73 | if self.arguments and self.arguments[0]: 74 | par['classes'].append(self.arguments[0]) 75 | 76 | self.state.nested_parse(StringList([self.options["header"]]), self.content_offset, par) 77 | self.state.nested_parse(self.content, self.content_offset, node) 78 | 79 | return [par, node] 80 | 81 | 82 | def add_assets(app): 83 | app.add_css_file(CSS_FILE) 84 | app.add_js_file(JS_FILE) 85 | 86 | 87 | def copy_assets(app, exception): 88 | if app.builder.name not in ['html', 'readthedocs'] or exception: 89 | return 90 | logger = logging.getLogger(__name__) 91 | logger.info('Copying contentui stylesheet/javascript... ', nonl=True) 92 | dest = os.path.join(app.builder.outdir, '_static', CSS_FILE) 93 | source = os.path.join(os.path.abspath(os.path.dirname(__file__)), CSS_FILE) 94 | copyfile(source, dest) 95 | dest = os.path.join(app.builder.outdir, '_static', JS_FILE) 96 | source = os.path.join(os.path.abspath(os.path.dirname(__file__)), JS_FILE) 97 | copyfile(source, dest) 98 | logger.info('done') 99 | 100 | 101 | def setup(app): 102 | app.add_directive('content-tabs', ContentTabsDirective) 103 | app.add_directive('tab-container', ContentTabsContainerDirective) 104 | app.add_directive('toggle-header', ToggleDirective) 105 | 106 | app.connect('builder-inited', add_assets) 107 | app.connect('build-finished', copy_assets) 108 | -------------------------------------------------------------------------------- /docs/example-all.rst: -------------------------------------------------------------------------------- 1 | .. _example-all: 2 | 3 | All-in-One Example 4 | ------------------ 5 | 6 | .. container:: left-col 7 | 8 | .. toggle-header:: 9 | :header: Example 1 **Show/Hide Code** 10 | 11 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor 12 | incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis 13 | nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. 14 | Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu 15 | fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in 16 | culpa qui officia deserunt mollit anim id est laborum 17 | 18 | .. toggle-header:: rubric 19 | :header: Example 2 20 | 21 | Sed ut perspiciatis, unde omnis iste natus error sit voluptatem 22 | accusantium doloremque laudantium, totam rem aperiam eaque ipsa, quae 23 | ab illo inventore veritatis et quasi architecto beatae vitae dicta 24 | sunt, explicabo. Nemo enim ipsam voluptatem, quia voluptas sit, 25 | aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos, 26 | qui ratione voluptatem sequi nesciunt, neque porro quisquam est, qui 27 | dolorem ipsum, quia dolor sit, amet, consectetur, adipisci velit, sed 28 | quia non numquam eius modi tempora incidunt, ut labore et dolore magnam 29 | aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum 30 | exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex 31 | ea commodi consequatur? Quis autem vel eum iure reprehenderit, qui in 32 | ea voluptate velit esse, quam nihil molestiae consequatur, vel illum, 33 | qui dolorem eum fugiat, quo voluptas nulla pariatur? At vero eos et 34 | accusamus et iusto odio dignissimos ducimus, qui blanditiis praesentium 35 | voluptatum deleniti atque corrupti, quos dolores et quas molestias 36 | excepturi sint, obcaecati cupiditate non provident, similique sunt in 37 | culpa, qui officia deserunt mollitia animi, id est laborum et dolorum 38 | fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam 39 | libero tempore, cum soluta nobis est eligendi optio, cumque nihil 40 | impedit, quo minus id, quod maxime placeat, facere possimus, omnis 41 | voluptas assumenda est, omnis dolor repellendus. Temporibus autem 42 | quibusdam et aut officiis debitis aut rerum necessitatibus saepe 43 | eveniet, ut et voluptates repudiandae sint et molestiae non recusandae. 44 | Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis 45 | voluptatibus maiores alias consequatur aut perferendis doloribus 46 | asperiores repellat. 47 | 48 | .. container:: content-tabs right-col 49 | 50 | .. tab-container:: python 51 | :title: Python 52 | 53 | .. rubric:: Definition 54 | 55 | .. code-block:: python 56 | 57 | my_api.signin() 58 | 59 | .. rubric:: Example request 60 | 61 | .. code-block:: python 62 | 63 | import my_api 64 | my_api.signin('username', 'password') 65 | 66 | .. tab-container:: php 67 | :title: PHP 68 | 69 | .. rubric:: Definition 70 | 71 | .. code-block:: php 72 | 73 | MyApi::signin(); 74 | 75 | .. rubric:: Example request 76 | 77 | .. code-block:: php 78 | 79 | include 'my-api.php'; 80 | MyApi::signin('username', 'password'); 81 | 82 | Additional 83 | ~~~~~~~~~~ 84 | 85 | .. content-tabs:: left-col 86 | 87 | .. tab-container:: ex1 88 | :title: Example 1 89 | 90 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor 91 | incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis 92 | nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. 93 | Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu 94 | fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in 95 | culpa qui officia deserunt mollit anim id est laborum 96 | 97 | .. tab-container:: ex2 98 | :title: Example 2 99 | 100 | Sed ut perspiciatis, unde omnis iste natus error sit voluptatem 101 | accusantium doloremque laudantium, totam rem aperiam eaque ipsa, quae 102 | ab illo inventore veritatis et quasi architecto beatae vitae dicta 103 | sunt, explicabo. Nemo enim ipsam voluptatem, quia voluptas sit, 104 | aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos, 105 | qui ratione voluptatem sequi nesciunt, neque porro quisquam est, qui 106 | dolorem ipsum, quia dolor sit, amet, consectetur, adipisci velit, sed 107 | quia non numquam eius modi tempora incidunt, ut labore et dolore magnam 108 | aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum 109 | exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex 110 | ea commodi consequatur? Quis autem vel eum iure reprehenderit, qui in 111 | ea voluptate velit esse, quam nihil molestiae consequatur, vel illum, 112 | qui dolorem eum fugiat, quo voluptas nulla pariatur? At vero eos et 113 | accusamus et iusto odio dignissimos ducimus, qui blanditiis praesentium 114 | voluptatum deleniti atque corrupti, quos dolores et quas molestias 115 | excepturi sint, obcaecati cupiditate non provident, similique sunt in 116 | culpa, qui officia deserunt mollitia animi, id est laborum et dolorum 117 | fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam 118 | libero tempore, cum soluta nobis est eligendi optio, cumque nihil 119 | impedit, quo minus id, quod maxime placeat, facere possimus, omnis 120 | voluptas assumenda est, omnis dolor repellendus. Temporibus autem 121 | quibusdam et aut officiis debitis aut rerum necessitatibus saepe 122 | eveniet, ut et voluptates repudiandae sint et molestiae non recusandae. 123 | Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis 124 | voluptatibus maiores alias consequatur aut perferendis doloribus 125 | asperiores repellat. 126 | 127 | .. content-tabs:: right-col 128 | 129 | 130 | .. tab-container:: python 131 | :title: Python 132 | 133 | .. rubric:: Description for Python 134 | 135 | .. tab-container:: php 136 | :title: PHP 137 | 138 | .. rubric:: Description for PHP 139 | --------------------------------------------------------------------------------