Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
lakhman committed Dec 20, 2017
0 parents commit 1133c73
Show file tree
Hide file tree
Showing 152 changed files with 3,121 additions and 0 deletions.
17 changes: 17 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
*.pyc
tmp
build
dist
parts
eggs
_build
/.tox
develop-eggs
.eggs
.cache
*.egg
*.egg-info
.idea
.python-version
.coverage
htmlcov
17 changes: 17 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
language: python
sudo: false
dist: trusty
cache: pip

matrix:
include:
- python: '2.7'
env: TOXENV=py27
- python: '3.3.6'
env: TOXENV=py336

install:
- pip install -U tox

script:
- tox -- -v
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License

Copyright (c) 2016-2017 Anil Lakhman https://anil.io

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
32 changes: 32 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
=========================================
``restructuredWeb`` directives for Sphinx
=========================================

.. image:: https://img.shields.io/pypi/v/sphinx.svg
:target: https://pypi.python.org/pypi/Sphinx

.. image:: https://travis-ci.org/lakhman/restructuredWeb.svg?branch=master
:target: https://travis-ci.org/sphinx-doc/sphinx

A collection of directives to be used with `Sphinx <https://github.com/sphinx-doc/sphinx>`_.

----------
Installing
----------

Install from PyPI.

.. code-block:: shell
pip install -U restructuredWeb
Enable the extension in your ``conf.py``.

.. code-block:: python
extensions = [
# Add the extension in your conf.py
'restructuredWeb',
]
**Demo site:** https://lakhman.github.io/restructuredBootstrap/
28 changes: 28 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
future
#
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile --output-file requirements.txt setup.py
#
alabaster==0.7.10 # via sphinx
babel==2.4.0 # via sphinx
certifi==2017.4.17 # via requests
chardet==3.0.4 # via requests
docutils==0.13.1 # via sphinx
idna==2.5 # via requests
imagesize==0.7.1 # via sphinx
jinja2==2.9.6 # via sphinx
markupsafe==1.0 # via jinja2
pygments==2.2.0 # via sphinx
pytz==2017.2 # via babel
requests==2.18.1 # via sphinx
six==1.10.0
snowballstemmer==1.2.1 # via sphinx
sphinx==1.6.3
sphinxcontrib-websupport==1.0.1 # via sphinx
typing==3.6.1 # via sphinx
urllib3==1.21.1 # via requests

# The following packages are considered to be unsafe in a requirements file:
# setuptools
36 changes: 36 additions & 0 deletions restructuredWeb/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
# Copyright (c) 2017 - Anil Lakhman - MIT License
# -----------------------------------------------------------------------------
from .adsense import setup as adsense_setup
from .configuration_block import setup as configuration_block_setup
from .codepen import setup as codepen_setup
from .gist import setup as gist_setup
from .layout import setup as layout_setup
from .jsfiddle import setup as jsfiddle_setup
from .javascript import setup as javascript_setup
from .css import setup as css_setup
from .ted import setup as ted_setup
from .twitter import setup as twitter_setup
from .youtube import setup as youtube_setup


def setup(app):
adsense_setup(app)
configuration_block_setup(app)
codepen_setup(app)
gist_setup(app)
layout_setup(app)
javascript_setup(app)
jsfiddle_setup(app)
css_setup(app)
ted_setup(app)
twitter_setup(app)
youtube_setup(app)

return {
'version': '0.1',
'parallel_read_safe': False,
'parallel_write_safe': True
}
87 changes: 87 additions & 0 deletions restructuredWeb/adsense.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
# Copyright (c) 2017 - Anil Lakhman - MIT License
# -----------------------------------------------------------------------------
from docutils import nodes
from docutils.parsers.rst import Directive
from docutils.parsers.rst import directives


class Adsense(Directive):
"""
Adsense Directive
"""

required_arguments, optional_arguments = 0, 1
final_argument_whitespace = False
has_content = False
option_spec = {
'format': directives.class_option,
'class': directives.class_option
}

def run(self):
node = adsense()

if self.arguments:
node.attributes['data-ad-slot'] = self.arguments[0]
else:
node.attributes['data-ad-slot'] = False

# Default to auto if nothing passed by user
node['data-ad-format'] = self.options.get('format', 'auto')
node['classes'] += self.options.get('class', [])

return [node] + []


class adsense(nodes.Element):
pass


def visit_adsense(self, node):
client_id = self.builder.config['adsense_client_id']
if not client_id:
self.builder.app.warn(
'adsense_client_id was False, check your conf.py. ["%s"]' %
self.builder.current_docname)
raise nodes.SkipNode

user_slots = self.builder.config['adsense_slots']
ad_slot = node.attributes['data-ad-slot']

# Use default slot if nothing was passed
if not node.attributes['data-ad-slot']:
ad_slot = self.builder.config['adsense_default_slot']

# Load from our user slot list if we have one
if user_slots:
for slot in user_slots:
if slot == ad_slot:
ad_slot = user_slots[slot]

if not ad_slot or not ad_slot.isdigit():
self.builder.app.warn('Skipping adsense slot as it\'s invalid in "%s"'
% self.builder.current_docname)
raise nodes.SkipNode

raw_tpl = '<ins class="adsbygoogle" style="display:block" ' \
'data-ad-client="%s" data-ad-slot="%s" data-ad-format="%s"></ins>'
tpl = raw_tpl % (client_id, ad_slot, node.attributes['data-ad-format'])

if node['classes']: # Add a wrapping div
self.body.append('<div class="%s">\n%s\n</div>\n' %
(' '.join(node['classes']), tpl))
else: # Regular Adsense snippet (no wrapping)
self.body.append(tpl + '\n')

raise nodes.SkipNode


def setup(app):
app.add_directive('adsense', Adsense)
app.add_config_value('adsense_client_id', '', 'html')
app.add_config_value('adsense_slots', {}, 'html')
app.add_config_value('adsense_default_slot', '', 'html')
app.add_node(adsense, html=(visit_adsense, None))
111 changes: 111 additions & 0 deletions restructuredWeb/codepen.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
# Copyright (c) 2017 - Anil Lakhman - MIT License
# -----------------------------------------------------------------------------
from docutils import nodes
from docutils.parsers.rst import Directive, directives
import re

DEFAULT_CODEPEN_THEME = 'light'


class Codepen(Directive):
"""
Codepen Directive
"""
required_arguments, optional_arguments = 1, 0
final_argument_whitespace = False
has_content = False
option_spec = {
'height': directives.length_or_percentage_or_unitless,
'preview': directives.flag,
'theme': directives.unchanged,
'tabs': directives.unchanged,
}

theme = None

def run(self):
if hasattr(self.state.document.settings, 'env'):
env = self.state.document.settings.env
codepen_theme = env.app.config.codepen_theme
else:
codepen_theme = DEFAULT_CODEPEN_THEME

node = codepen()
node['theme'] = codepen_theme

# Overrides the app config
if 'theme' in self.options:
node['theme'] = self.options.get('theme')

if 'preview' in self.options:
node['preview'] = self.options.get('preview')

if 'height' in self.options:
node['height'] = self.options.get('height')

if 'tabs' in self.options:
node['tabs'] = self.options.get('tabs')

try:
if self.arguments:
url_match = re.match(
r"^https://codepen\.io/(.+[^/])/pen/(.+[^/])/?$",
self.arguments[0])
if url_match and len(url_match.groups()):
node['url'] = self.arguments[0]
node['author'] = url_match.group(1)
node['slug'] = url_match.group(2)
else:
raise ValueError('Invalid Codepen URL.')
except ValueError as err:
e = '%s for "%s" directive: "%s".'
raise self.error(e % (err, self.name,
self.arguments[0]))

return [node] + []


class codepen(nodes.Element):
pass


def visit_codepen(self, node):
atts = ['data-embed-version="2"']

if 'height' in node:
px = directives.length_or_percentage_or_unitless(node['height'], 'px')
atts.append(
'data-height="{}" style="height: {};"'.format(node['height'], px))
else:
atts.append(
'data-height="{}" style="height: {};"'.format('265', '265px'))

if 'author' in node and 'slug' in node:
atts.append('data-slug-hash="{}"'.format(node['slug']))
atts.append('data-user="{}"'.format(node['author']))

if 'theme' in node:
atts.append('data-theme-id="{}"'.format(node['theme']))

if 'preview' in node:
atts.append('data-preview="true"')

if 'tabs' in node:
atts.append('data-default-tab="{}"'.format(node['tabs']))

props = " ".join(atts)

node = '<div class="rst-codepen"><p class="codepen" {}>{}</p></div>'.format(
props, node['url'])
self.body.append(node + '\n')

raise nodes.SkipNode


def setup(app):
app.add_config_value('codepen_theme', DEFAULT_CODEPEN_THEME, 'env')
app.add_directive('codepen', Codepen)
app.add_node(codepen, html=(visit_codepen, None))
Loading

0 comments on commit 1133c73

Please sign in to comment.