Partial Markdown Doc Support

This commit is contained in:
BJ Dierkes 2017-11-18 21:36:08 -06:00
parent 30bd9653d0
commit 10bf9872ad
67 changed files with 148 additions and 5120 deletions

View File

@ -4,6 +4,8 @@
class Meta(object):
"""
# Testing
Model that acts as a container class for a meta attributes for a larger
class. It stuffs any kwarg it gets in it's init as an attribute of itself.
@ -17,6 +19,19 @@ class Meta(object):
setattr(self, key, dict_obj[key])
def johnny(self):
"""
Testing...
# Arguments
spam (Spam): 200g of spam
eggs (Egg): 3 eggs
ham (Ham): As much ham as you like.
"""
pass
class MetaMixin(object):
"""

View File

@ -3,56 +3,52 @@ The Alarm Extension provides easy access to setting an application alarm to
handle timing out operations. See the
`Python Signal Library <https://docs.python.org/3.5/library/signal.html>`_.
Requirements
------------
**Requirements**
* No external dependencies.
* Only available on Unix/Linux
Configuration
-------------
**Configuration**
This extension does not honor any application configuration settings.
Usage
-----
**Usage**
.. code-block:: python
```python
import time
from cement import App, CaughtSignal
import time
from cement import App, CaughtSignal
class MyApp(App):
class Meta:
label = 'myapp'
exit_on_close = True
extensions = ['alarm']
class MyApp(App):
class Meta:
label = 'myapp'
exit_on_close = True
extensions = ['alarm']
with MyApp() as app:
try:
app.run()
app.alarm.set(3, "The operation timed out after 3 seconds!")
with MyApp() as app:
try:
app.run()
app.alarm.set(3, "The operation timed out after 3 seconds!")
# do something that takes time to operate
time.sleep(5)
# do something that takes time to operate
time.sleep(5)
app.alarm.stop()
app.alarm.stop()
except CaughtSignal as e:
print(e.msg)
app.exit_code = 1
except CaughtSignal as e:
print(e.msg)
app.exit_code = 1
```
Looks like:
.. code-block:: console
$ python myapp.py
ERROR: The operation timed out after 3 seconds!
Caught signal 14
```
$ python myapp.py
ERROR: The operation timed out after 3 seconds!
Caught signal 14
```
"""
import signal

View File

@ -1,47 +0,0 @@
baseurl = "http://builtoncement.com/"
title = "Cement Framework Documentation"
languageCode = "en-us"
theme = "docuapi"
# Code higlighting settings
pygmentsCodefences = true
pygmentsCodeFencesGuesSyntax = false
pygmentsOptions = ""
pygmentsStyle = "monokai"
# The monokai stylesheet is included in the base template.
pygmentsUseClasses = true
defaultContentLanguage = "en"
search = true
toc_footers = [
"[![Continuous Integration Status](https://travis-ci.org/datafolklabs/cement.svg)](https://travis-ci.org/datafolklabs/cement)",
"[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/datafolklabs/cement?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)",
# "[DOCS](http://builtoncement.com/2.99/)",
# "[CODE](http://github.com/datafolklabs/cement/)",
# "[PYPI](http://pypi.python.org/pypi/cement/)",
# "[GITTER](https://gitter.im/datafolklabs/cement)",
]
# Configure the language example tabs.
[[params.language_tabs]]
key = "code"
name = "Code Examples / Usage"
# [[params.language_tabs]]
# key = "go"
# name = "Go"
# [[params.language_tabs]]
# key = "ruby"
# name = "Ruby"
# [[params.language_tabs]]
# key = "bash"
# name = "BASH"
#Languages
[languages]
[languages.en]
languageName = "English"
weight = 2
title = "Cement Framework"

View File

@ -1,49 +0,0 @@
# ChangeLog
## 2.99.1 - DEVELOPMENT (will be released as dev/2.99.2 or stable/3.0.0)
This is a complete fork from Cement 2 code base. Please continue to use
stable versions of Cement 2, until Cement 3.0.0 is released.
Bugs:
- `[ext.redis]` Unable To Set Redis Host
- [Issue #440](https://github.com/datafolklabs/cement/issues/440)
Features:
- `[core]` Add Docker / Docker Compose Support
- [Issue #439](https://github.com/datafolklabs/cement/issues/439)
Refactoring:
- *Too many to reference*
Incompatible:
- `[core]` Replace Interfaces with ABC Base Classes
- [Issue #192](https://github.com/datafolklabs/cement/issues/192)
- `[core.foundation]` Rename `CementApp` to `App`.
- `[core.handler]` Rename `CementBaseHandler` to `Handler`
- `[core.handler]` Drop deprecated backend globals
- `[core.hook]` Drop deprecated backend globals
- `[core.controller]` Drop `CementBaseController`
- `[ext.argcomplete]` No longer shipped with Cement.
- `[ext.reload_config]` No longer shipped with Cement.
- `[ext.configobj]` No longer shipped with Cement.
- `[ext.json_configobj]` No longer shipped with Cement.
- `[ext.yaml_configobj]` No longer shipped with Cement.
- `[ext.genshi]` No longer shipped with Cement.
- `[ext.argparse]` ArgparseController.Meta.default_func is not `_default`, and
will print help info and exit. Can now set this to `None` as well to
pass/exit.
- [Issue #426](https://github.com/datafolklabs/cement/issues/426)
Deprecation:
* *Everything with deprecation notices in Cement < 3*

View File

@ -1,141 +0,0 @@
---
weight: 4
title: Cleanup
---
# Application Cleanup
> Automatic Cleanup (Builtin)
```python
from cement import App
### both .setup() / .close() called automatically by `with`
with App('myapp') as app:
app.run()
### the above is equivalent to
app = App('myapp')
app.setup()
app.run()
app.close()
```
The concept of 'cleanup' after application run time is nothing new. What
happens during 'cleanup' all depends on the application. This might mean
closing and deleting temporary files, removing session data, or deleting a PID
(Process ID) file.
To allow for application cleanup not only within your program, but also
external plugins and extensions, there is the `app.close()` function that
must be called after `app.run()` regardless of any exceptions or runtime
errors. Note that `app.close()` is called automatically when using the
Python `with` operator, so it is not generally something you call directly,
but it is important to know how and when it is called.
Calling `app.close()` ensures that the ``pre_close`` and ``post_close``
framework hooks are run, allowing extensions/plugins/etc to cleanup after the
program runs.
## Exit Status and Error Codes
> Setting Exit Code on Application Close
```python
from cement import App
### set exit_on_close for production use
class MyApp(App):
class Meta:
label = 'myapp'
exit_on_close = True
### disable it for testing
class MyAppForTesting(MyApp):
class Meta:
exit_on_close = False
with MyApp() as app:
try:
app.run()
except Exception as e:
### set exit code to use on app.close()
app.exit_code = 1
```
You can optionally set the status code that your application exists with via
`App.exit_code`, however you must also ensure that the meta option
`App.Meta.exit_on_close` is enabled.
<aside class="warning">
Note that Cement will not call SystemExit unless App.Meta.exit_on_close is
enabled. You will find that calling SystemExit in testing is very
problematic, therefore you will likely want to enable App.Meta.exit_on_close
for production, but not for testing.
</aside>
Note that the default exit code is `0`, and any *uncaught exceptions* will
cause the application to exit with a code of `1` (error).
## Running Cleanup Code
> Example: Running Cleanup Code Via Hooks
```python
import os
from tempfile import mkstemp
from cement import App, init_defaults
defaults = init_defaults('myapp')
defaults['myapp']['tmp_file'] = mkstemp()[1]
def my_cleanup_hook(app):
# do something with app...
tmp_file = app.config.get('myapp', 'tmp_file')
if os.path.exists(tmp_file):
app.log.warning('removing tmp file: %s' % tmp_file)
os.remove(tmp_file)
class MyApp(App):
class Meta:
label = 'myapp'
config_defaults = defaults
hooks = [
('pre_close', my_cleanup_hook),
]
with MyApp() as app:
app.run()
```
> Usage
```
$ python myapp.py
WARNING: removing tmp file: /tmp/tmpifmxsfid
```
Any extension, plugin, or even the application itself that has 'cleanup'
code should do so within the `pre_close` or `post_close` hooks to ensure
that it gets run. See the `Hooks` section of the documentation for more
information on running framework hooks.

View File

@ -1,326 +0,0 @@
---
weight: 3
title: Hooks
---
# Hooks
Hooks allow developers to tie into different pieces of the application, and/or
the Cement Framework. A hook can be defined anywhere, be it internally in the
application, or in a plugin. Once a hook is defined, functions can be
registered to that hook so that when the hook is called, all functions
registered to that hook will be executed. By defining a hook, you are saying
that you are going to honor that hook somewhere in your application or plugin.
Using descriptive hook names is good for clarity. For example, the name
`pre_database_connect` is obviously a hook that will be run just before a
database connection is attempted.
The most important thing to remember when defining hooks is to properly
document them. Include whether anything is expected in return
or what, if any, arguments will be passed to the hook functions when called.
## Defining Hooks
> Defining a Hook via App.Meta
```python
from cement import App
class MyApp(App):
class Meta:
label = 'myapp'
define_hooks = [
'my_example_hook',
]
```
> Defining a Hook via App.setup()
```python
class MyApp(App):
# ...
def setup(self):
super()
self.hook.define('my_example_hook')
```
A hook can be defined anywhere, however it is best-practice to define the hook
as early as possible. A hook definition simply gives a label to the hook, and
allows the developer (or third-party plugin developers) to register functions
to that hook. It's label is arbitrary.
## Registering Hook Functions
> Registering Hook Functions via App.Meta
```python
from cement import App
def my_hook1(app):
# do something with app
pass
def my_hook2(app):
# do something with app
pass
class MyApp(App):
class Meta:
label = 'myapp'
### list of tuples: ( 'hook_label', <hook_function> )
hooks = [
('post_argument_parsing', my_hook1),
('pre_close', my_hook2),
]
```
> Registering Hook Functions via App.setup()
```python
class MyApp(App):
# ...
def setup(self):
super()
### register hook functions
self.hook.register('post_argument_parsing', my_hook1)
self.hook.register('pre_close', my_hook2)
```
A hook label is just an arbitrary identifier, but the functions registered to
that hook are what get run when the hook is called. Registering a hook
function should also be done early on in the bootstrap process, any time after
the application has been created, after the hook is defined, and before the
hook is run. Note that every hook is different, and therefore should be
clearly documented by the 'owner' of the hook (application developer, plugin
developer, etc).
What you return depends on what the developer defining the hook is expecting.
Each hook is different, and the nature of the hook determines whether you need
to return anything or not. That is up to the developer. Also, the `*args`
and `**kwargs` coming in depend on the developer. You have to be familiar
with the purpose of the defined hook in order to know whether you are
receiving any `*args` or `**kwargs`.
## Running Hooks
> Running a Hook
```python
with MyApp() as app:
app.run()
for res in app.hook.run('my_example_hook'):
# do something with res?
pass
```
Now that a hook is defined, and functions have been registered to that hook,
all that is left is to run it. As you can see in the example, we iterate over
the hook rather than just calling `app.hook.run()` by itself. This is
necessary because `app.hook.run()` yields the results from each hook function
as they are run. Hooks can be run anywhere **after** the hook is defined, and
hooks are registered to that hook.
<aside class='warning'>
Keep in mind, you don't want to run a hook until after the application load
process... meaning, after all plugins and other code are loaded. If you
receive an error that the hook doesn't exist, then you are trying to register
a hook too soon before the hook is defined. Likewise, if it doesn't seem like
your hook is running and you don't see it mentioned in `--debug` output, you
might be registering your hook **after** the hook has already run.
</aside>
## Controlling Hook Run Order
> Example: Hook Run Order
```python
from cement import App
### define hook functions
def func1(app):
print('Inside hook func1')
def func2(app):
print('Inside hook func2')
def func3(app):
print('Inside hook func3')
class MyApp(App):
class Meta:
label = 'myapp'
### define my_hook
define_hooks = [
'my_hook',
]
### register functions to my_hook
hooks = [
('my_hook', func1, weight=0),
('my_hook', func2, weight=100),
('my_hook', func3, weight=-99),
]
with MyApp() as app:
app.run()
### execute my_hook
for res in app.hook.run('my_hook', app)
pass
```
> Usage
```bash
$ python myapp.py
Inside hook func3
Inside hook func1
Inside hook func2
```
Sometimes you might have a very specific purpose in mind for a hook, and need
it to run before or after other functions in the same hook. For that reason
there is an optional `weight` parameter that can be passed when registering
a hook function.
As you can see in the example, it doesnt matter what order we register the
hook, the weight runs then in order from lowest to highest.
## Cement Framework Hooks
> Example Usage of Framework Hooks
```python
from cement import App
### handle arguments before app.run() is called
def inspect_arguments(app):
if app.pargs.foo is not None:
print('Foo Argument Was Passed!')
class MyApp(App):
class Meta:
label = 'myapp'
hooks = [
('post_argument_parsing', inspect_arguments),
]
with MyApp() as app:
app.args.add_argument('--foo')
app.run()
```
> Usage
```bash
$ python myapp.py --foo bar
Foo Argument Was Passed!
```
Cement has a number of hooks that tie into the framework.
### pre_setup
Run first when `App.setup()` is called. The application object is
passed as an argument. Nothing is expected in return.
### post_setup
Run last when `App.setup()` is called. The application object is
passed as an argument. Nothing is expected in return.
### pre_run
Run first when `App.run()` is called. The application object is
passed as an argument. Nothing is expected in return.
### post_run
Run last when `App.run()` is called. The application object is
passed as an argument. Nothing is expected in return.
### pre_argument_parsing
Run after `App.run()` is called, just *before* argument parsing happens.
The application object is passed as an argument to these hook
functions. Nothing is expected in return.
### post_argument_parsing
Run after `App.run()` is called, just *after* argument parsing happens.
The application object is passed as an argument to these hook
functions. Nothing is expected in return.
This hook is generally useful where the developer needs to perform actions
based on the arguments that were passed at command line, but before the
logic of `App.run()` happens.
### pre_render
Run first when App.render() is called. The application object, and
data dictionary are passed as arguments. Must return either the original
data dictionary, or a modified one.
Note: This does not affect anything that is 'printed' to console.
### post_render
Run last when `App.render()` is called. The application object, and
rendered output text are passed as arguments. Must return either the original
output text, or a modified version.
### pre_close
Run first when `App.close()` is called. This hook should be used by plugins
and extensions to do any 'cleanup' at the end of program execution. Nothing
is expected in return.
### post_close
Run last when `App.close()` is called. Most use cases need `pre_close`,
however this hook is available should one need to do anything after all other
'close' operations.
### signal
Run when signal handling is enabled, and the defined signal handler callback
is executed. This hook should be used by the application, plugins, and
extensions to perform any actions when a specific signal is caught. Nothing
is expected in return.

View File

@ -1,105 +0,0 @@
---
weight: 1
title: Cement Framework
---
# Cement Framework v2.99.1
> Installation via PyPi (Stable)
```
$ pip install cement
```
> Hello World Example
```python
from cement import App
with App('myapp') as app:
app.run()
app.log.info('Hello World!')
```
> Usage
```
$ python helloworld.py --help
usage: helloworld [-h] [--debug] [--quiet]
optional arguments:
-h, --help show this help message and exit
--debug toggle debug output
--quiet suppress all output
$ python helloworld.py
INFO: Hello World!
```
Let's hope that this long sentence doesn't get eaten up by the `slate monsters of old`.
And this one also I want to see what this looks `App.Meta.config_files == 'test'`.
<aside class="warning">
This is the Portland branch of Cement, intended for future-looking and
non-backward-compatible development. It is a complete fork of Cement 2, and
will eventually become Cement 3. It is guaranteed to be broken! Please use
Cement 2 in production until stable/3.0.0 is released.
</aside>
Cement is an advanced Application Framework for Python, with a primary focus
on Command Line Interfaces (CLI). Its goal is to introduce a standard, and
feature-full platform for both simple and complex command line applications
as well as support rapid development needs without sacrificing quality.
Cement is flexible, and it's use cases span from the simplicity of a
micro-framework to the complexity of a mega-framework. Whether it's a single
file script, or a multi-tier application, Cement is the foundation you've been
looking for.
The first commit to Git was on Dec 4, 2009. Since then, the framework has
seen several iterations in design, and has continued to grow and improve
since it's inception. Cement is the most stable, and complete framework for
command line and backend application development.
Cement core features include (but are not limited to):
- Core pieces of the framework are customizable via handlers/interfaces
- Handler system connects implementation classes with Interfaces
- Extension handler interface to easily extend framework functionality
- Config handler supports parsing multiple config files into one config
- Argument handler parses command line arguments and merges with config
- Log handler supports console and file logging
- Plugin handler provides an interface to easily extend your application
- Output handler interface renders return dictionaries to console
- Cache handler interface adds caching support for improved performance
- Controller handler supports sub-commands, and nested controllers
- Hook support adds a bit of magic to apps and also ties into framework
- Zero external dependencies* (not including optional extensions)
- 100% test coverage using `nose` and `coverage`
- 100% PEP8 and style compliant using `flake8`
- Extensive Sphinx documentation
- Tested on Python 3.5+
- Does not support Python 2.x
<aside class="notice">
Some optional extensions that are shipped with the mainline Cement sources do
require external dependencies. It is the responsibility of the application
developer to include these dependencies along with their application, as
Cement explicitly does not include them.
</aside>
**More Information**
- [Documentation](http://builtoncement.com/2.99/)
- [Source Code](http://github.com/datafolklabs/cement/)
- [PyPi](http://pypi.python.org/pypi/cement/)
- [Travis Continuous Integration Testing](https://travis-ci.org/datafolklabs/cement/)
- [Gitter Discussion Channel](https://gitter.im/datafolklabs/cement/)
**License**
The Cement CLI Application Framework is Open Source and is distributed under
the BSD License (three clause). Please see the
[LICENSE](https://raw.githubusercontent.com/datafolklabs/cement/master/LICENSE)
file included with this software.

View File

@ -1,864 +0,0 @@
---
title: "Quick Start Overview"
weight: 2
slug: quickstart
---
# Quickstart Overview
This section is intended to give a brief overview of some of the most commonly
used core features of Cement. Please do not be discouraged if you don't
"get it" right away. Please also do not think, "is this it?". This is not
intended to be an exhaustive end-all-be-all coverage of every feature of the
framework.
Some assumptions are being made here. Primarily, we assume that you've used
and are familiar with Python. The quickstart is intended to give a high level
look at using Cement. Please dive deeper into the individual sections after
the quickstart in order to gain a better understanding of each component.
[comment]: <> (--------------------------------------------------------------)
## The Application Object
> Using Cement App Directly
```python
from cement import App
with App('myapp') as app:
app.run()
```
> Sub-classing Cement App
```python
from cement import App
class MyApp(App):
class Meta:
label = 'myapp'
with MyApp() as app:
app.run()
```
> Usage
```bash
$ python myapp.py --help
usage: myapp [-h] [--debug] [--quiet]
optional arguments:
-h, --help show this help message and exit
--debug toggle debug output
--quiet suppress all output
```
The core of your application starts with the Cement `App` object, which we
will refer to throughout this documentation as:
* `App` - The uninstantiated Cement `App` base class
* `MyApp` - The uninstatiated/sub-classed Cement application you are creating
* `app` - The instantiated application object
Technically, Cement `App` can be used direcly (as in the example), however in
practice you will almost always sub-class `App` in order to configure it for
your needs (I.e. `MyApp`).
[comment]: <> (--------------------------------------------------------------)
## MetaMixin's
> Sub-classing Cement App / Overriding Metadata Options
```python
from cement import App, init_defaults
# define default application configuration settings
defaults = init_defaults('myapp')
defaults['myapp']['foo'] = 'bar'
class MyApp(App):
class Meta:
label = 'myapp'
config_defaults = defaults
with MyApp() as app:
app.run()
print("Foo => %s" % app.config.get('myapp', 'foo'))
```
> Usage
```
$ python myapp.py
Foo => bar
```
Cement uses `MetaMixin` classes everywhere, which allows the framework to
define default functionality but also provides an easy mechanism for
developers to override and customize.
This is implemented by declaring a `Meta` class, under your application and/or
other Cement Handler classes. All Meta-options can also be overridden by any
`**kwargs` that are passed to the parent class that is being instantiated.
I.e. `App('myapp', config_defaults={'foo': 'bar'})`
Nearly every Cement class has an associated `Meta` class, which we often
refer to as `App.Meta`, `SomeHandlerClass.Meta`, etc. The
instantiated object is refered to in code as `app._meta`,
`some_handler._meta`, etc.
[comment]: <> (--------------------------------------------------------------)
## Interfaces and Handlers
> Overriding Default Framework Handlers
```python
from cement import App
from cement.ext.ext_configparser import ConfigParserConfigHandler
class MyConfigHandler(ConfigParserConfigHandler):
class Meta:
label = 'my_config_handler'
# do something to subclass/re-implement
# config handler here...
class MyApp(App):
class Meta:
label = 'myapp'
config_handler = 'my_config_handler'
handlers = [
MyConfigHandler
]
```
All aspects of the framework are broken up into interfaces, and handlers.
Interfaces define some functionality, and Handlers implement that
functionality. Cement defines the following interfaces:
- `extension` - Framework extensions loading
- `log` - Logging to console/file
- `config` - Application Configuration defaults, overrides by file, etc
- `mail` - Mail sending (smtp, etc)
- `plugin` - Application plugin loading
- `output` - Output rendering (JSON, Yaml, Mustache Templates, etc)
- `argument` - Command line argument parsing
- `controller` - Command dispatch (sub-commands, sub-command arguments, etc)
- `cache` - Key/Value data store (memcached, redis, etc)
For example, the builtin configuration handler
`ConfigParserConfigHandler`, implements the `config` interface. Handlers
are referred to by the interfaces they implement, such as
`config.configparser`, `config.json`, `config.yaml`, etc.
<aside class="info">
Application developers can also define their own interfaces, allowing
customization by plugins.
</aside>
### Overriding Via Configuration Files
> Overriding Via Configuration File
```
[myapp]
### override App.Meta.mail_handler
mail_handler = my_mail_handler
```
`MyApp` defines and/or defaults to builtin handlers for all of the above
listed core handlers. Whatever the application code defines is the default,
however you can also override via the configuration file(s) as in the example
to the right.
For example, imagine that your default `mail_handler` is `smtp` for
sending email via your local SMTP server. This is a configuration that might
very on a per-user/environment basis. Via the application configuration, you
could override this with an alternative mail handler like
`mail_handler=some_other_mail_handler`
[comment]: <> (--------------------------------------------------------------)
## Configuration
> myapp.py
```python
from cement import App, init_defaults
defaults = init_defaults('myapp')
defaults['myapp']['foo'] = 'bar'
class MyApp(App):
class Meta:
label = 'myapp'
config_defaults = defaults
with MyApp() as app:
app.run()
print("Foo => %s" % app.config.get('myapp', 'foo'))
```
> ~/.myapp.conf
```
[myapp]
foo = not-bar
```
> Usage
```
$ python myapp.py
Foo => not-bar
```
> Alternative Configuration Handler Example
```python
from cement import App
class MyApp(App):
class Meta:
label = 'myapp'
extensions = ['yaml']
config_handler = 'yaml'
config_extension = '.yml'
```
> ~/.myapp.yml
```yaml
myapp:
foo: not-bar
```
Cement supports loading multiple configuration files out-of-the-box.
Configurations loaded from files are merged in, overriding the applications
default settings (`App.Meta.config_defaults`). The default configuration
handler is `ConfigParserConfigHandler`, based on
[ConfigParser](https://docs.python.org/3/library/configparser.html) in the
standard library, and is instantiated as `app.config`.
Cement looks for configuration files in the most common places such as:
- `/etc/myapp/myapp.conf`
- `~/.myapp.conf`
- `~/.myapp/config`
- etc
The list of configuration file paths can be customized via the meta option
`App.Meta.config_files` as well as their extension (i.e. `.conf`) can also
be easily modified with `App.Meta.config_extension`.
The builtin configuration handler `ConfigParserConfigHandler` uses common
unix-like config files where `blocks` or `sections` are defined with brackets:
I.e. `[myapp]`, `[myplugin]`, `[interface.handler]`, etc
Additional support for the following file formats is provided
via optional extensions:
* Json
* Yaml
<aside class="info">
ConfigHandler's provide dropin replacements for the default
ConfigParserConfigHandler, and are often based on it. For example, the
JsonConfigHandler and YamlConfigHandler extensions do nothing more than
support reading alternative file formats. Accessing the config settings in
the app is exactly the same
</aside>
All extensions and application plugins can support customization loaded from
the application configuration file under the section `[interface.handler]`.
For example, the `ColorLogHandler` extension reads it's configuration from
`[log.colorlog]`.
[comment]: <> (--------------------------------------------------------------)
## Arguments
> Simple Arguments Defined With Cement App
```python
from cement import App
with App('myapp') as app:
app.args.add_argument('-f', '--foo',
help='notorous foo option',
dest='foo')
app.run()
# do something with parsed arguments
if app.pargs.foo is not None:
print("Foo Argument => %s" % app.pargs.foo)
```
> Arguments Defined by Controllers
```python
from cement import App, Controller, ex
class Base(Controller):
class Meta:
label = 'base'
arguments = [
# list of tuples in the format `( [], {} )`
( [ '-f', '--foo' ],
{ 'help' : 'notorious foo option',
'dest' : 'foo' } ),
]
@ex(hide=True)
def _default(self):
print('Inside BaseController._default()')
# do something with parsed arguments
if self.app.pargs.foo is not None:
print("Foo Argument => %s" % self.app.pargs.foo)
class MyApp(App):
class Meta:
label = 'myapp'
handlers = [Base]
with MyApp() as app:
app.run()
```
> Usage
```
$ python myapp.py --help
usage: myapp [-h] [--debug] [--quiet] [-f FOO]
optional arguments:
-h, --help show this help message and exit
--debug toggle debug output
--quiet suppress all output
-f FOO, --foo FOO notorous foo option
$ python myapp.py -f bar
Foo Argument => bar
```
Argument parsing is based on the standard
[Argparse](https://docs.python.org/3/library/argparse.html) library, with the
same usage that you're familiar with. The argument handler
`ArgparseArgumentHandler` is instantiated as `app.args`, arguments are defined
with `app.args.add_argument()`, and parsed arguments are stored as
`app.args.parsed_args` (or more conveniently `app.pargs` for easy reference).
### Arguments Defined by Controllers
The power of the framework comes into play when we start talking about
application controllers that streamline the process of mapping arguments and
sub-commands to actions/functions as in the example (more on that later).
[comment]: <> (--------------------------------------------------------------)
## Logging
> Logging Example
```python
from cement import App
with App('myapp') as app:
app.run()
# log messages to console and file
app.log.info('this is an info message')
app.log.warning('this is an warning message')
app.log.error('this is an error message')
app.log.fatal('this is an fatal message')
app.log.debug('this is an debug message')
```
> Logging Configuration Example
```
[myapp]
log_handler = logging
[log.logging]
to_console = true
file = /path/to/myapp.log
level = warning
```
Logging is based on the standard
[Logging](https://docs.python.org/3/library/logging.html) library, with the
same usage you're familiar with. The logging facility is customizable via the
`[log.logging]` section of an applications configuration:
- `level` - The level at which to start logging (`INFO`, `WARNING`, `ERROR`,
`FATAL`, `DEBUG`, etc).
- `file` (*path*) - File path to log to.
- `to_console` (*bool*) - Whether or not to log to console.
- `rotate` (*bool*) - Whether or not to rotate the log file when it hits
`max_bytes`
- `max_bytes` (*int*) - Maximum file size in bytes before file gets rotated
- `max_files` (*int*) - Maximum number of log files to keep after rotating
Cement also includes the following optional extensions that provide drop-in
replacements for the default log handler:
- `ColorlogHandler` - Provides colorized log output via the
[Colorlog](https://github.com/borntyping/python-colorlog) library.
[comment]: <> (--------------------------------------------------------------)
## Output
> Standard Output via Print Statements
```python
from cement import App
with App('myapp') as app:
print('About Run MyApp!')
app.run()
```
> Mixed Template/JSON Output Example
```python
from cement import App
class MyApp(App):
class Meta:
label = 'myapp'
### add optional extensions
extensions = ['json', 'mustache']
### set the default output handler
output_handler = 'mustache'
### external template directory
template_dir = '/path/to/templates'
### internal template module (shipped with app code)
template_module = 'myapp.templates'
with MyApp() as app:
app.run()
### create some data
data = {
'foo' : 'bar',
}
### render data using mustache template (by default)
app.render(data, 'example.m')
```
> Mustache Template: /path/to/templates/example.m
```
The value of foo={{foo}}.
```
> Usage
```
$ python test.py --help
usage: myapp [-h] [--debug] [--quiet] [-o {json}]
optional arguments:
-h, --help show this help message and exit
--debug toggle debug output
--quiet suppress all output
-o {json} output handler
$ python myapp.py
The value of foo=bar
$ python myapp.py -o json
{"foo": "bar"}
```
By default, Cement does not define any output handlers. Just like any other
app, you are free to `print()` to console all you like or use the builtin
logging facility. That said, more complex applications will benefit greatly
by separating the output from the logic. Think of output handling as the
`view` in a traditional
[MVC Framework](https://en.wikipedia.org/wiki/Model-view-controller).
Cement ships with several types of extensions that produce output in
different forms, including the following:
- Text Rendered From Template Files
- Programatic Structures (JSON, Yaml, etc)
- Tabulated (like MySQL, etc)
- Etc
The following output handlers ship with Cement:
- `Json` - Produces JSON output from dicts
- `Yaml` - Produces Yaml output from dicts
- `Mustache` - Produces text output rendered from
[Mustache](http://mustache.github.io/) templates
- `Handlebars` - Produces text output rendered from
[Handlebars](https://github.com/wbond/pybars3) templates
- `Jinja2` - Produces text output rendered from
[Jinja2](http://jinja.pocoo.org/) templates
- `Tabulated` - Produces tabulated text output rendered via the
[Tabulate](https://pypi.python.org/pypi/tabulate) library.
### Multiple Output Handler Support
One of the unique features of Cement is that you can build your application
to support multiple output handlers and formats. Output handlers have a
special attribute that allows them to be exposed via the CLI option
`-o` (configurable via `App.Meta.core_handler_override_options`). Therefore,
you might have default text based output rendered from Mustache templates, but
optionally output programatic structures *from the same dict* when necessary
(i.e.`$ myapp -o json`).
[comment]: <> (--------------------------------------------------------------)
## Controllers
> Example: Application Base Controller
```python
from cement import App, Controller, ex
class Base(Controller):
class Meta:
label = 'base'
arguments = [
# list of tuples in the format `( [], {} )`
( [ '-a' ],
{ 'help' : 'example a option',
'dest' : 'a' } ),
]
def _default(self):
print('Inside Base._default()')
if self.app.pargs.a:
print('Received Option: -a')
@ex(
help='sub-command under base controller',
arguments=[
( [ '-b' ],
{ 'help' : 'cmd1 b option' } ),
]
)
def cmd1(self):
print('Inside Base.cmd1()')
if self.app.pargs.b:
print('Recieved Option: -b')
class MyApp(App):
class Meta:
label = 'myapp'
handlers = [
Base,
]
with MyApp() as app:
app.run()
```
> Usage
```bash
### help output shows base namespace arguments and sub-commands
$ python myapp.py --help
usage: myapp [-h] [--debug] [--quiet] [-a A] {cmd1} ...
optional arguments:
-h, --help show this help message and exit
--debug toggle debug output
--quiet suppress all output
-a A example a option
sub-commands:
{cmd1}
cmd1 sub-command under base controller
$ python myapp.py -a foo
Inside Base._default()
Received Option: -a
### sub-commands support their own arguments
$ python myapp.py cmd1 --help
usage: myapp cmd1 [-h] [-b B]
optional arguments:
-h, --help show this help message and exit
-b B cmd1 b option
$ python myapp.py cmd1 -b foo
Inside Base.cmd1()
Recieved Option: -b
```
Controllers provide a common means of organizing application logic into
relevant chunks of code, as well as the ability for plugins and extensions to
extend an applications capabilities. It is the `Controller` piece of the
traditional
[MVC Framework](https://en.wikipedia.org/wiki/Model-view-controller).
The first controller is called `base`, and if registered will take over
runtime control when `app.run()` is called. What this means is, instead of
Cement calling `app.args.parse_arguments()` directly, the application dispatch
is handed over to the `base` controller, that is then responsible for
parsing and handling arguments. This is what we call `Runtime Dispatch`.
The most notable action of `Runtime Dispatch` is mapping arguments and
sub-commands to their respective controllers and functions. For example, the
default action when running `$ myapp` without any arguments or sub-commands
is to execute the `BaseController._default()` function.
### Nested / Embedded Controllers
Cement supports two types of controller `stacking`:
- `nested` - The arguments and commands are nested under a sub-parser whose
label is that of the controller. For example, a nested controller with a
label of `my-nested-controller` would be called as
`$ myapp my-nested-controller sub-command`.
- `embedded` - The arguments and commands are embedded within it's parent
controller, therefore appearing as if they were defined by the parent
itself. A sub-command under an embedded controller would be called as
`$ myapp sub-command`.
Controllers can be stacked on other controllers as many levels deep as
necessary. An `embedded` controller can be stacked on top of a `nested`
controller, and vice versa. There is little, if any, limitation.
### Controller Arguments vs Command Arguments
Both Controllers and their sub-commands can have arguments defined. Think of
controllers as the primary namespace. It's arguments should be globally
relevant within that namespace. A sub-command within the namespace can have
it's own arguments, but are only relevant to that sub-command.
For example: `$ myapp -a my-controller -b my-sub-command -c`
In the above example, `-a` is relevant to the global scope of the entire
application because it is defined on the `base` controller. Option `-b` is
relevant to the scope of `my-controller` and all sub-commands under it.
Finally, `-c` is only relevant to the `my-sub-command` and has no use
elsewhere.
### Exposing Sub-Commands
By default, no commands are exposed to the CLI except that a `_default()`
function will be called if no sub-command is passed (configurable by
`Controller.Meta.default_func`).
To expose a function as a sub-command, you must decorate it with `@ex()`.
It's usage is simple, and supports the following parameters:
- `hide` (*bool*) - Whether or not to display in `--help` output.
- `arguments` (*list*) - Argument list of tuples in the format `( [], {} )`,
that are passed to `Argparse.add_argument(*args, **kwargs)`.
- `**kwargs` - Additional keyword arguments are passed directly to Argparse
when creating the sub-parser for this command.
<aside class='info'>
Why `ex`? Well, `ex` is short for `expose`, and just so happens that `@ex(`
is exactly `4` characters, making it lineup perfectly with indented
parameters. It makes things more readable, more-better.
</aside>
[comment]: <> (--------------------------------------------------------------)
## Framework Extensions
> Example: Using Framework Extensions
```python
from time import sleep
from cement import App
class MyApp(App):
class Meta:
label = 'myapp'
extensions = [
'alarm',
]
with MyApp() as app:
app.run()
### set an alarm based on the max allowed run time
app.alarm.set(3, "The operation timed out after 3 seconds!")
### do something that takes time to operate
sleep(5)
### stop the alarm if it ran within the time frame
app.alarm.stop()
```
> Usage
```bash
$ python myapp.py
ERROR: The operation timed out after 3 seconds!
Traceback (most recent call last):
File "myapp.py", line 20, in <module>
sleep(5)
File "cement/core/foundation.py", line 123, in cement_signal_handler
raise exc.CaughtSignal(signum, frame)
cement.core.exc.CaughtSignal: Caught signal 14
```
Cement's Interfaces and Handlers system make extending the framework easy, and
limitless. Cement ships dozens of extensions that either alter existing
funtionality, or add to it. For example, the default logging facility
provides basic logging capabilities, however with a single line of code an
application can instead use the `colorlog` extension to enable colorized
console logging.
The example provides a quick look at using the `alarm` extension to handle
application timeouts of long running operations
Cement includes (but not limited to) the following extensions:
- `alarm` - Provides easy access to setting an application alarm to handle
timing out operations
- `argparse` - Provides `ArgparseArgumentHandler` and `ArgparseController`
handlers built on Argparse
- `colorlog` - Provides `ColorLogHandler` that produces colorized console
logging
- `configparser` - Provides `ConfigParserConfigHandler` handler for
application configuration built on on ConfigParser
- `daemon` - Provides daemonization, pidfile management, user/group
context switching, etc
- `handlebars` - Provides `HandlebarsOutputHandler` to render text output from
Handlerbars templates
- `jinja2` - Provides `Jinja2OutputHandler` to render text output from
Jinja2 templates
- `json` - Provides `JsonConfigHandler` and `JsonOutputHandler` to read
JSON configuration files, and produce JSON structured output.
- `logging` - Provides `LoggingLogHandler` for standard application
logging
- `memcached` - Providers `MemcachedCacheHandler` for caching built on
Memcached
- `mustache` - Provides `MustacheOutputHandler` to render text output from
Mustache templates
- `plugin` - Provides `CementPluginHandler` for application plugin support
- `redis` - Provides `RedisCacheHandler` for caching built on Redis
- `smtp` - Provides `SMTPMailHandler` for email messaging
- `tabulate` - Provides `TabulateOutputHandler` for text output tabularized
like MySQL, etc
- `watchdog` - Provides cross-platform directory/file monitoring in order to
handle filesystem events as they occur.
- `yaml` - Providers `YamlConfigHandler` and `YamlOutputHandler` to read
Yaml configuration files, and produce Yaml structured output.
[comment]: <> (--------------------------------------------------------------)
## Application Plugins
FIX ME
[comment]: <> (--------------------------------------------------------------)
## Hooks
> Example: Executing Code Via Hooks
```python
from cement import App
def my_example_hook(app):
print('Inside my_example_hook()')
class MyApp(App):
class Meta:
label = 'myapp'
hooks = [
('post_argument_parsing', my_example_hook),
]
with MyApp() as app:
app.run()
```
> Usage
```bash
$ python myapp.py
Inside my_example_hook()
```
Hooks provide developers the ability to tie into the framework, and
applications without direct access to the runtime. For example, a plugin
might need to execute some code after arguments have been parsed, but before
controller sub-commands are dispatched. As a plugin developer, you don't have
direct access to the applications runtime code but you can still tie into it
with the builtin `post_argument_parsing` hook.
Cement defines several hooks that tie in to specific points throughout the
application life cycle, however application developers can also define their
own hooks allowing others to tie elsewhere, when needed.

View File

@ -1,28 +0,0 @@
---
weight: 99
title: Upgrading
---
# Upgrading
This section outlines any information and changes that might need to be made
in order to update your application built on previous versions of Cement.
## 2.8.x to 2.9.x
Cement 2.9 introduces a few incompatible changes from the previous 2.8 stable
release, as noted in the :ref:`ChangeLog <changelog>`.
### Deprecated: cement.core.interface.list()
This function should no longer be used in favor of
`CementApp.handler.list_types()`. It will continue to work throughout
Cement 2.x, however is not compatible if
`CementApp.Meta.use_backend_globals == False`.
Related:
* [Issue #366](https://github.com/datafolklabs/cement/issues/366)
* [Issue #376](https://github.com/datafolklabs/cement/issues/376)

View File

@ -1,11 +0,0 @@
<style>
.content code {
background-color: rgba(0,0,0,0.05);
word-break: keep-all;
hyphens: none;
padding: 3px;
border-radius: 3px;
@extend %code-font;
}
</style>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

View File

@ -1 +0,0 @@
docuapi

View File

@ -1,194 +0,0 @@
Apache License
==============
_Version 2.0, January 2004_
_&lt;<http://www.apache.org/licenses/>&gt;_
### Terms and Conditions for use, reproduction, and distribution
#### 1. Definitions
“License” shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.
“Licensor” shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.
“Legal Entity” shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, “control” means **(i)** the power, direct or
indirect, to cause the direction or management of such entity, whether by
contract or otherwise, or **(ii)** ownership of fifty percent (50%) or more of the
outstanding shares, or **(iii)** beneficial ownership of such entity.
“You” (or “Your”) shall mean an individual or Legal Entity exercising
permissions granted by this License.
“Source” form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.
“Object” form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.
“Work” shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included
in or attached to the work (an example is provided in the Appendix below).
“Derivative Works” shall mean any work, whether in Source or Object form, that
is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative Works
shall not include works that remain separable from, or merely link (or bind by
name) to the interfaces of, the Work and Derivative Works thereof.
“Contribution” shall mean any work of authorship, including the original version
of the Work and any modifications or additions to that Work or Derivative Works
thereof, that is intentionally submitted to Licensor for inclusion in the Work
by the copyright owner or by an individual or Legal Entity authorized to submit
on behalf of the copyright owner. For the purposes of this definition,
“submitted” means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor for
the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as “Not a Contribution.”
“Contributor” shall mean Licensor and any individual or Legal Entity on behalf
of whom a Contribution has been received by Licensor and subsequently
incorporated within the Work.
#### 2. Grant of Copyright License
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form.
#### 3. Grant of Patent License
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by such Contributor
that are necessarily infringed by their Contribution(s) alone or by combination
of their Contribution(s) with the Work to which such Contribution(s) was
submitted. If You institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
Contribution incorporated within the Work constitutes direct or contributory
patent infringement, then any patent licenses granted to You under this License
for that Work shall terminate as of the date such litigation is filed.
#### 4. Redistribution
You may reproduce and distribute copies of the Work or Derivative Works thereof
in any medium, with or without modifications, and in Source or Object form,
provided that You meet the following conditions:
* **(a)** You must give any other recipients of the Work or Derivative Works a copy of
this License; and
* **(b)** You must cause any modified files to carry prominent notices stating that You
changed the files; and
* **(c)** You must retain, in the Source form of any Derivative Works that You distribute,
all copyright, patent, trademark, and attribution notices from the Source form
of the Work, excluding those notices that do not pertain to any part of the
Derivative Works; and
* **(d)** If the Work includes a “NOTICE” text file as part of its distribution, then any
Derivative Works that You distribute must include a readable copy of the
attribution notices contained within such NOTICE file, excluding those notices
that do not pertain to any part of the Derivative Works, in at least one of the
following places: within a NOTICE text file distributed as part of the
Derivative Works; within the Source form or documentation, if provided along
with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of
the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works that
You distribute, alongside or as an addendum to the NOTICE text from the Work,
provided that such additional attribution notices cannot be construed as
modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as a whole,
provided Your use, reproduction, and distribution of the Work otherwise complies
with the conditions stated in this License.
#### 5. Submission of Contributions
Unless You explicitly state otherwise, any Contribution intentionally submitted
for inclusion in the Work by You to the Licensor shall be under the terms and
conditions of this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify the terms of
any separate license agreement you may have executed with Licensor regarding
such Contributions.
#### 6. Trademarks
This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.
#### 7. Disclaimer of Warranty
Unless required by applicable law or agreed to in writing, Licensor provides the
Work (and each Contributor provides its Contributions) on an “AS IS” BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
including, without limitation, any warranties or conditions of TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
solely responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with Your exercise of
permissions under this License.
#### 8. Limitation of Liability
In no event and under no legal theory, whether in tort (including negligence),
contract, or otherwise, unless required by applicable law (such as deliberate
and grossly negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, incidental,
or consequential damages of any character arising as a result of this License or
out of the use or inability to use the Work (including but not limited to
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
any and all other commercial damages or losses), even if such Contributor has
been advised of the possibility of such damages.
#### 9. Accepting Warranty or Additional Liability
While redistributing the Work or Derivative Works thereof, You may choose to
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
other liability obligations and/or rights consistent with this License. However,
in accepting such obligations, You may act only on Your own behalf and on Your
sole responsibility, not on behalf of any other Contributor, and only if You
agree to indemnify, defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason of your
accepting any such warranty or additional liability.
_END OF TERMS AND CONDITIONS_
### APPENDIX: How to apply the Apache License to your work
To apply the Apache License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets `[]` replaced with your own
identifying information. (Don't include the brackets!) The text should be
enclosed in the appropriate comment syntax for the file format. We also
recommend that a file or class name and description of purpose be included on
the same “printed page” as the copyright notice for easier identification within
third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,26 +0,0 @@
#
# Makefile to perform rebuilds after changes to asset files.
#
# n.b. you must install fswatch (OS X: `brew install fswatch`)
#
# To start live live rebuilds, use the following command:
# $ make serve
#
# TODO: Figure a way to watch recursive
SLATE_DIR := /Users/bep/dev/clone/slate
WATCH_PATHS = ./assets/*.* ./assets/javascripts/*.* ./assets/javascripts/app/*.*
WATCH_PATHS := ${WATCH_PATHS} ./assets/stylesheets/*.*
build:
go run bundler.go -slate=${SLATE_DIR}
serve:
@make build
@fswatch -o ${WATCH_PATHS} | xargs -n1 -I{} make build
release:
git tag -a ${version} -m "Release ${version}"
git push --follow-tags

View File

@ -1,69 +0,0 @@
**DocuAPI** is a beautiful multilingual API documentation theme for [Hugo](http://gohugo.io/). This theme is built on top of the beautiful work of [Robert Lord](https://github.com/lord) and others on the [Slate](https://github.com/lord/slate) project ([Apache 2 License](https://github.com/lord/slate/blob/master/LICENSE)).
<br/>
> Visit the [demo site](https://docuapi.com/).
<br/>
![Screenshot DocuAPI Example site](https://raw.githubusercontent.com/bep/docuapi/master/images/screenshot.png)
## Use
See the [exampleSite](https://github.com/bep/docuapi/tree/master/exampleSite) and more specific its site [configuration](https://github.com/bep/docuapi/blob/master/exampleSite/config.toml) for the available options.
**Note that this theme needs Pygments installed to render code samples. See [pygments.org](http://pygments.org/)**
**Most notable:** This theme will use all the (non drafts) pages in the site and build a single-page API documentation. Using `weight` in the page front matter is the easiest way to control page order.
If you want a different page selection, please provide your own `layouts/index.html` template.
## Hooks
When the fix for [#2549](https://github.com/spf13/hugo/issues/2549) is released we may do this with blocks, but until then you can provide some custom partials:
* `partials/hook_head_end.html` is inserted right before the `head` end tag. Useful for additional styles etc.
* `partials/hook_body_end.html` which should be clear by its name.
* `partials/hook_left_sidebar_start.html` the start of the left sidebar
* `partials/hook_left_sidebar_end.html` the end of the left sidebar
* `partials/hook_left_sidebar_logo.html` the log `img` source
The styles and Javascript import are also put in each partial and as such can be overridden if really needed:
* `partials/styles.html`
* `partials/js.html`
## Develop the Theme
**Note:** In most situations you will be well off just using the theme and maybe in some cases provide your own template(s). Please refer to the [Hugo Documentation](http://gohugo.io/overview/introduction/) for that.
But you may find styling issues, etc., that you want to fix. Those Pull Requests are warmly welcomed!
**If you find issues that obviously belongs to [Slate](https://github.com/lord/slate), then please report/fix them there, and we will pull in the latest changes here.**
This project provides a very custom asset bundler in [bundler.go](https://github.com/bep/docuapi/blob/master/bundler.go) written in Go.
It depends on `libsass` to build, so you will need `gcc` (a C compiler) to build it for your platform. If that is present, you can try:
* `go get -u -v .`
* `go run bundler.go` (this will clone Slate to a temp folder)
* Alternative to the above if you already have Slate cloned somewhere: `go run bundler.go -slate=/path/to/Slate`
All options:
```bash
go run bundler.go -h
-minify
apply minification to output Javascript, CSS etc. (default true)
-slate string
the path to the Slate source, if not set it will be cloned from https://github.com/lord/slate.git
```
With `make` and `fswatch` (OSX only, I believe) available, you can get a fairly enjoyable live-reloading development experience for all artifacts by running:
* `hugo server` in your Hugo site project.
* `make serve` in the theme folder.

View File

@ -1,2 +0,0 @@
+++
+++

View File

@ -1,168 +0,0 @@
//= require ../lib/_jquery
/*
Copyright 2008-2013 Concur Technologies, Inc.
Licensed under the Apache License, Version 2.0 (the "License"); you may
not use this file except in compliance with the License. You may obtain
a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations
under the License.
*/
(function (global) {
'use strict';
var languages = [];
global.setupLanguages = setupLanguages;
global.activateLanguage = activateLanguage;
function activateLanguage(language) {
if (!language) return;
if (language === "") return;
$(".lang-selector a").removeClass('active');
$(".lang-selector a[data-language-name='" + language + "']").addClass('active');
// Mod to match Pygments from Hugo: div.highlight > pre code.language-ruby
var codeSelectorPrefix = ".highlight code.language-";
for (var i=0; i < languages.length; i++) {
$(codeSelectorPrefix + languages[i]).parentsUntil(".highlight").hide();
$(".lang-specific." + languages[i]).hide();
}
$(codeSelectorPrefix + language).parentsUntil(".highlight").show();
$(".lang-specific." + language).parentsUntil(".highlight").show();
global.toc.calculateHeights();
// scroll to the new location of the position
if ($(window.location.hash).get(0)) {
$(window.location.hash).get(0).scrollIntoView(true);
}
}
// parseURL and stringifyURL are from https://github.com/sindresorhus/query-string
// MIT licensed
// https://github.com/sindresorhus/query-string/blob/7bee64c16f2da1a326579e96977b9227bf6da9e6/license
function parseURL(str) {
if (typeof str !== 'string') {
return {};
}
str = str.trim().replace(/^(\?|#|&)/, '');
if (!str) {
return {};
}
return str.split('&').reduce(function (ret, param) {
var parts = param.replace(/\+/g, ' ').split('=');
var key = parts[0];
var val = parts[1];
key = decodeURIComponent(key);
// missing `=` should be `null`:
// http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters
val = val === undefined ? null : decodeURIComponent(val);
if (!ret.hasOwnProperty(key)) {
ret[key] = val;
} else if (Array.isArray(ret[key])) {
ret[key].push(val);
} else {
ret[key] = [ret[key], val];
}
return ret;
}, {});
};
function stringifyURL(obj) {
return obj ? Object.keys(obj).sort().map(function (key) {
var val = obj[key];
if (Array.isArray(val)) {
return val.sort().map(function (val2) {
return encodeURIComponent(key) + '=' + encodeURIComponent(val2);
}).join('&');
}
return encodeURIComponent(key) + '=' + encodeURIComponent(val);
}).join('&') : '';
};
// gets the language set in the query string
function getLanguageFromQueryString() {
if (location.search.length >= 1) {
var language = parseURL(location.search).language
if (language) {
return language;
} else if (jQuery.inArray(location.search.substr(1), languages) != -1) {
return location.search.substr(1);
}
}
return false;
}
// returns a new query string with the new language in it
function generateNewQueryString(language) {
var url = parseURL(location.search);
if (url.language) {
url.language = language;
return stringifyURL(url);
}
return language;
}
// if a button is clicked, add the state to the history
function pushURL(language) {
if (!history) { return; }
var hash = window.location.hash;
if (hash) {
hash = hash.replace(/^#+/, '');
}
history.pushState({}, '', '?' + generateNewQueryString(language) + '#' + hash);
// save language as next default
localStorage.setItem("language", language);
}
function setupLanguages(l) {
var defaultLanguage = localStorage.getItem("language");
languages = l;
var presetLanguage = getLanguageFromQueryString();
if (presetLanguage) {
// the language is in the URL, so use that language!
activateLanguage(presetLanguage);
localStorage.setItem("language", presetLanguage);
} else if ((defaultLanguage !== null) && (jQuery.inArray(defaultLanguage, languages) != -1)) {
// the language was the last selected one saved in localstorage, so use that language!
activateLanguage(defaultLanguage);
} else {
// no language selected, so use the default
activateLanguage(languages[0]);
}
}
// if we click on a language tab, activate that language
$(function() {
$(".lang-selector a").on("click", function() {
var language = $(this).data("language-name");
pushURL(language);
activateLanguage(language);
return false;
});
window.onpopstate = function() {
activateLanguage(getLanguageFromQueryString());
};
});
})(window);

View File

@ -1,43 +0,0 @@
// The section(s) below are just pulled over from _variables.scss in Slate and adjusted.
// Make the selected code language a nice blue.
$lang-select-active-bg: $nav-active-bg;
// Make the main background color slightly lighter than the original.
$main-bg: lighten(#eaf2f6, 2%);
// This will be added as the last import to the original Slate screen.css.scs. TOOD(bep) Print?
.content {
// prevent clearing of higlight divs
&>div.highlight {
clear:none;
}
}
.toc-footer {
.translations-title {
background-color: $nav-subitem-bg;
padding: 10px $nav-padding;
color: $nav-text;
font-size: 12px;
}
}
// Getting the paths just right for Android and iOS and friends is hard ...
@font-face {
font-family:'slate';
src:url(/fonts/slate.eot?-syv14m);
src:url(../fonts/slate.eot?#iefix-syv14m) format("embedded-opentype"),
url(../fonts/slate.woff2?-syv14m) format("woff2"),
url(../fonts/slate.woff?-syv14m) format("woff"),
url(../fonts/slate.ttf?-syv14m) format("truetype"),
url(../fonts/slate.svg?-syv14m#slate) format("svg");
font-weight: normal;
font-style: normal;
}

View File

@ -1,65 +0,0 @@
.highlight pre { background-color: #272822; }
.highlight .hll { background-color: #272822; }
.highlight .c { color: #75715e } /* Comment */
.highlight .err { color: #960050; background-color: #1e0010 } /* Error */
.highlight .k { color: #66d9ef } /* Keyword */
.highlight .l { color: #ae81ff } /* Literal */
.highlight .n { color: #f8f8f2 } /* Name */
.highlight .o { color: #f92672 } /* Operator */
.highlight .p { color: #f8f8f2 } /* Punctuation */
.highlight .cm { color: #75715e } /* Comment.Multiline */
.highlight .cp { color: #75715e } /* Comment.Preproc */
.highlight .c1 { color: #75715e } /* Comment.Single */
.highlight .cs { color: #75715e } /* Comment.Special */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .kc { color: #66d9ef } /* Keyword.Constant */
.highlight .kd { color: #66d9ef } /* Keyword.Declaration */
.highlight .kn { color: #f92672 } /* Keyword.Namespace */
.highlight .kp { color: #66d9ef } /* Keyword.Pseudo */
.highlight .kr { color: #66d9ef } /* Keyword.Reserved */
.highlight .kt { color: #66d9ef } /* Keyword.Type */
.highlight .ld { color: #e6db74 } /* Literal.Date */
.highlight .m { color: #ae81ff } /* Literal.Number */
.highlight .s { color: #e6db74 } /* Literal.String */
.highlight .na { color: #a6e22e } /* Name.Attribute */
.highlight .nb { color: #f8f8f2 } /* Name.Builtin */
.highlight .nc { color: #a6e22e } /* Name.Class */
.highlight .no { color: #66d9ef } /* Name.Constant */
.highlight .nd { color: #a6e22e } /* Name.Decorator */
.highlight .ni { color: #f8f8f2 } /* Name.Entity */
.highlight .ne { color: #a6e22e } /* Name.Exception */
.highlight .nf { color: #a6e22e } /* Name.Function */
.highlight .nl { color: #f8f8f2 } /* Name.Label */
.highlight .nn { color: #f8f8f2 } /* Name.Namespace */
.highlight .nx { color: #a6e22e } /* Name.Other */
.highlight .py { color: #f8f8f2 } /* Name.Property */
.highlight .nt { color: #f92672 } /* Name.Tag */
.highlight .nv { color: #f8f8f2 } /* Name.Variable */
.highlight .ow { color: #f92672 } /* Operator.Word */
.highlight .w { color: #f8f8f2 } /* Text.Whitespace */
.highlight .mf { color: #ae81ff } /* Literal.Number.Float */
.highlight .mh { color: #ae81ff } /* Literal.Number.Hex */
.highlight .mi { color: #ae81ff } /* Literal.Number.Integer */
.highlight .mo { color: #ae81ff } /* Literal.Number.Oct */
.highlight .sb { color: #e6db74 } /* Literal.String.Backtick */
.highlight .sc { color: #e6db74 } /* Literal.String.Char */
.highlight .sd { color: #e6db74 } /* Literal.String.Doc */
.highlight .s2 { color: #e6db74 } /* Literal.String.Double */
.highlight .se { color: #ae81ff } /* Literal.String.Escape */
.highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */
.highlight .si { color: #e6db74 } /* Literal.String.Interpol */
.highlight .sx { color: #e6db74 } /* Literal.String.Other */
.highlight .sr { color: #e6db74 } /* Literal.String.Regex */
.highlight .s1 { color: #e6db74 } /* Literal.String.Single */
.highlight .ss { color: #e6db74 } /* Literal.String.Symbol */
.highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */
.highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */
.highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */
.highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */
.highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */
.highlight .gh { } /* Generic Heading & Diff Header */
.highlight .gu { color: #75715e; } /* Generic.Subheading & Diff Unified/Comment? */
.highlight .gd { color: #f92672; } /* Generic.Deleted & Diff Deleted */
.highlight .gi { color: #a6e22e; } /* Generic.Inserted & Diff Inserted */

View File

@ -1,470 +0,0 @@
// Copyright 2016 Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>s. All rights reserved.
//
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
"bufio"
"bytes"
"flag"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/tdewolff/minify"
"github.com/tdewolff/minify/js"
shutil "github.com/termie/go-shutil"
libsass "github.com/wellington/go-libsass"
)
const (
// The source for the styles and scripts.
// If you have Slate locally, set the slate flag.
slateRepo = "https://github.com/lord/slate.git"
)
var (
logger *log.Logger = log.New(os.Stdout, "bundler: ", log.Ldate|log.Ltime|log.Lshortfile)
staticSlateDirs = []string{
"images",
"fonts",
}
)
func main() {
var (
slateSourceDir = flag.String("slate", "", "the path to the Slate source, if not set it will be cloned from "+slateRepo)
minify = flag.Bool("minify", true, "apply minification to output Javascript, CSS etc.")
)
flag.Parse()
pwd, err := os.Getwd()
if err != nil {
logger.Fatal(err)
}
bundler := newBundler(
*slateSourceDir,
filepath.Join(pwd, "static", "slate"), *minify)
if err := bundler.init(); err != nil {
logger.Fatal(err)
}
if err := bundler.fetchSlateIfNeeded(); err != nil {
logger.Fatal(err)
}
if err := bundler.replaceSlateSourcesInTheme(); err != nil {
logger.Fatal("Failed to move Slate sources: ", err)
}
if err := bundler.mergeAndAdjustStyles(); err != nil {
logger.Fatal("Failed to edit Slate sources: ", err)
}
if err := bundler.createJSBundles(); err != nil {
logger.Fatal("Failed to bundle JS: ", err)
}
if err := bundler.compileSassSources(); err != nil {
logger.Fatal("Failed compile SASS stylesheets: ", err)
}
logger.Println("Done...")
}
type bundler struct {
slateSource string
slateTarget string
minify bool
// We do some mods to the Slate source (add some styles). Do that on a copy in here.
tmpSlateSource string
logger *log.Logger
}
func newBundler(slateSource, slateTarget string, minify bool) *bundler {
return &bundler{slateSource: slateSource, slateTarget: slateTarget, minify: minify, logger: logger}
}
func (b *bundler) init() error {
if err := os.RemoveAll(b.slateTarget); err != nil {
return err
}
if err := os.MkdirAll(b.slateTarget, os.ModePerm); err != nil {
return err
}
return nil
}
func (b *bundler) fetchSlateIfNeeded() error {
if b.slateSource != "" {
b.logger.Println("Use existing Slate clone in", b.slateSource)
if err := b.copySlateSourcesToModify(); err != nil {
return err
}
return nil
}
b.logger.Println("Fetch Slate from", slateRepo)
slateSource, err := ioutil.TempDir("", "docuapi")
if err != nil {
return fmt.Errorf("Failed to create tmpdir: %s", err)
}
if err := cloneSlateInto(slateSource); err != nil {
return fmt.Errorf("Failed to clone Slate: %s", err)
}
b.slateSource = slateSource
// This will be replaced on next build, so it is tempoary enough.
b.tmpSlateSource = slateSource
return nil
}
func (b *bundler) copySlateSourcesToModify() error {
slateSource, err := ioutil.TempDir("", "docuapi")
if err != nil {
return fmt.Errorf("Failed to create tmpdir: %s", err)
}
// We need to adapt the SASS source ... or learn how to use includeDirs ...
if err := shutil.CopyTree(
filepath.Join(b.slateSource, "source", "stylesheets"),
filepath.Join(slateSource, "source", "stylesheets"), nil); err != nil {
return fmt.Errorf("Failed to copy stylesheets: %s", err)
}
b.tmpSlateSource = slateSource
return nil
}
func (b *bundler) replaceSlateSourcesInTheme() error {
for _, staticDir := range staticSlateDirs {
b.logger.Println("Copy", staticDir)
if err := shutil.CopyTree(filepath.Join(b.slateSource, "source", staticDir), filepath.Join(b.slateTarget, staticDir), nil); err != nil {
return err
}
}
return nil
}
func (b *bundler) mergeAndAdjustStyles() error {
slateStylesheetsDir := filepath.Join(b.tmpSlateSource, "source", "stylesheets")
b.logger.Println("Compile SASS in", slateStylesheetsDir)
customImports := filepath.Join(b.slateTarget, "..", "..", "assets", "stylesheets")
// Copy custom SASS files into merged source. Should be able to do this by
// setting an includePath, but ...
fis, err := ioutil.ReadDir(customImports)
if err != nil {
return err
}
for _, fi := range fis {
if err := shutil.CopyFile(filepath.Join(customImports, fi.Name()), filepath.Join(slateStylesheetsDir, fi.Name()), false); err != nil {
return fmt.Errorf("failed to copy custom SASS: %s", err)
}
}
// Insert custom import
if err := replaceInFile(filepath.Join(slateStylesheetsDir, "screen.css.scss"),
"@import 'variables';\n@import 'icon-font';",
"@import 'variables';\n@import 'icon-font';\n@import 'docuapi';"); err != nil {
return err
}
return nil
}
func replaceInFile(filename, old, new string) error {
read, err := ioutil.ReadFile(filename)
if err != nil {
return err
}
nc := bytes.Replace(read, []byte(old), []byte(new), -1)
err = ioutil.WriteFile(filename, nc, os.ModePerm)
if err != nil {
return err
}
return nil
}
func (b *bundler) compileSassSources() error {
source := filepath.Join(b.tmpSlateSource, "source", "stylesheets")
target := filepath.Join(b.slateTarget, "stylesheets")
os.MkdirAll(target, os.ModePerm)
fis, err := ioutil.ReadDir(source)
if err != nil {
return err
}
for _, fi := range fis {
if strings.HasPrefix(fi.Name(), "_") {
continue
}
targetName := strings.TrimSuffix(fi.Name(), ".scss")
b.logger.Println("Compile", fi.Name(), "to", targetName)
cssFile, err := os.Create(filepath.Join(target, targetName))
if err != nil {
return err
}
outputStyle := libsass.NESTED_STYLE
if b.minify {
outputStyle = libsass.COMPRESSED_STYLE
}
comp, err := libsass.New(cssFile, nil,
libsass.OutputStyle(outputStyle),
libsass.Path(filepath.Join(source, fi.Name())),
)
if err != nil {
return err
}
if err := comp.Run(); err != nil {
return fmt.Errorf("SASS run failed: %s", err)
}
}
return nil
}
func (b *bundler) createJSBundles() error {
src := filepath.Join(b.slateSource, "source", "javascripts")
dst := filepath.Join(b.slateTarget, "javascripts")
overrides := filepath.Join(b.slateTarget, "..", "..", "assets", "javascripts")
jsB := newJSBundler(src, dst, overrides, b.minify)
return jsB.bundle()
}
func cloneSlateInto(dir string) error {
logger.Println("Clone Slate into", dir, "...")
cmd := exec.Command("git", "clone", "-b", "docuapi", slateRepo, dir)
return cmd.Run()
}
type jsBundler struct {
src string
dst string
minify bool
overridesSrc string
overrides map[string][]byte
logger *log.Logger
// Per bundle
seen map[string]bool
buff bytes.Buffer
}
func newJSBundler(src, dst, overridesSrc string, minify bool) *jsBundler {
return &jsBundler{src: src, dst: dst, overridesSrc: overridesSrc, minify: minify, logger: logger, overrides: make(map[string][]byte)}
}
func (j *jsBundler) readOverrides() error {
j.logger.Println("Looking for overrides in", j.overridesSrc)
return filepath.Walk(j.overridesSrc, func(path string, info os.FileInfo, err error) error {
if info.IsDir() {
return nil
}
libPath := strings.TrimPrefix(path, j.overridesSrc)
libPath = strings.TrimPrefix(libPath, string(filepath.Separator))
j.logger.Println("Adding override:", libPath)
libContent, err := ioutil.ReadFile(path)
if err != nil {
return err
}
j.overrides[libPath] = libContent
return nil
})
}
func (j *jsBundler) bundle() error {
if err := j.readOverrides(); err != nil {
return err
}
if err := os.MkdirAll(j.dst, os.ModePerm); err != nil {
return err
}
fis, err := ioutil.ReadDir(j.src)
if err != nil {
return err
}
for _, fi := range fis {
if !strings.HasSuffix(fi.Name(), ".js") {
continue
}
filename := filepath.Join(j.src, fi.Name())
if err := j.newBundle(filename); err != nil {
return err
}
var source bytes.Buffer
if j.minify {
j.logger.Println("Minify JS")
m := minify.New()
m.AddFunc("text/javascript", js.Minify)
if err := m.Minify("text/javascript", &source, &j.buff); err != nil {
return err
}
} else {
source = j.buff
}
if err = ioutil.WriteFile(filepath.Join(j.dst, fi.Name()), source.Bytes(), os.ModePerm); err != nil {
return fmt.Errorf("Failed to write to destination: %s", err)
}
}
return nil
}
func (j *jsBundler) newBundle(filename string) error {
j.logger.Println("New bundle from ", filename)
j.seen = make(map[string]bool)
j.buff.Reset()
j.buff.WriteString("\n\n// From bep's Poor Man's JS bundler // ----\n")
return j.handleFile(filename)
}
func (j *jsBundler) handleFile(filename string) error {
var (
overridenContent = j.getOverrideIfFound(filename)
currDir = filepath.Dir(filename)
libs []string
)
if overridenContent == nil {
file, err := os.Open(filename)
if err != nil {
return err
}
// TODO(bep) exclude the requires when writing to bundle
libs = j.extractRequiredLibs(file)
file.Close()
} else {
libs = j.extractRequiredLibs(bytes.NewReader(overridenContent))
}
for _, lib := range libs {
if j.seen[lib] {
continue
}
j.seen[lib] = true
lib += ".js"
libFilename := filepath.Join(currDir, lib)
//j.logger.Println("Handle lib", lib)
// Must write its dependencies first
if err := j.handleFile(libFilename); err != nil {
return err
}
var content []byte
var err error
content = j.getOverrideIfFound(libFilename)
if content == nil {
content, err = ioutil.ReadFile(libFilename)
if err != nil {
return err
}
}
_, err = j.buff.Write(content)
if err != nil {
return err
}
}
return nil
}
func (j *jsBundler) getOverrideIfFound(filename string) []byte {
libPath := strings.TrimPrefix(filename, j.src)
libPath = strings.TrimPrefix(libPath, string(filepath.Separator))
return j.overrides[libPath]
}
func (j *jsBundler) extractRequiredLibs(r io.Reader) []string {
const require = "//= require"
scanner := bufio.NewScanner(r)
var libs []string
for scanner.Scan() {
t := strings.TrimSpace(scanner.Text())
if strings.HasPrefix(t, require) {
libs = append(libs, strings.TrimSpace(t[len(require):]))
}
}
return libs
}

View File

@ -1 +0,0 @@
/public

View File

@ -1,71 +0,0 @@
theme = "docuapi"
themesdir = "../.."
languageCode = "en-us"
baseurl = "http://docuapi.com/"
title = "DocuAPI Example Site"
# Code higlighting settings
pygmentsCodefences = true
pygmentsCodeFencesGuesSsyntax = false
pygmentsOptions = ""
pygmentsStyle = "monokai"
# The monokai stylesheet is included in the base template.
pygmentsUseClasses = true
defaultContentLanguage = "en"
[params]
search = true
# Configure the language example tabs.
[[params.language_tabs]]
key = "go"
name = "Go"
[[params.language_tabs]]
key = "shell"
name = "Shell"
[[params.language_tabs]]
key = "ruby"
name = "Ruby"
[[params.language_tabs]]
key = "python"
name = "Python"
[[params.language_tabs]]
key = "javascript"
name = "Javascript"
#Languages
[languages]
[languages.en]
languageName = "English"
weight = 2
title = "DocuAPI Example Site"
# Left sidebar footer items. Use HTMl or Markdown.
toc_footers = [
"<a href='#'>Sign Up for a Developer Key</a>",
"Documentation Powered by [DocuAPI](https://github.com/bep/docuapi)",
"Hugo Theme by [bep](https://github.com/bep)"
]
[languages.en.blackfriday]
angledQuotes = false
hrefTargetBlank = true
[languages.nn]
languageName = "Nynorsk"
weight = 1
title = "DocuAPI-døme"
# Left sidebar footer items. Use HTMl or Markdown.
toc_footers = [
"<a href='#'>Registrer deg for ein utviklarnøkkel</a>",
"Dokumentasjonen er driven av [DocuAPI](https://github.com/bep/docuapi)",
"Hugo Theme av [bep](https://github.com/bep)"
]
[languages.nn.blackfriday]
# Norwegian uses angled quotes
angledQuotes = true
hrefTargetBlank = true

View File

@ -1,26 +0,0 @@
---
weight: 20
title: Errors
---
# Errors
<aside class="notice">This error section is stored in a separate file, errors.md. DocuAPI allows you to split the single page documentation in as many files as needed. Files are included in the default Hugo page order . One way of ordering the pages is by setting the page `weight` in the front matter. Pages with lower weight will be listed first.</aside>
The Kittn API uses the following error codes:
Error Code | Meaning
---------- | -------
400 | Bad Request -- Your request sucks
401 | Unauthorized -- Your API key is wrong
403 | Forbidden -- The kitten requested is hidden for administrators only
404 | Not Found -- The specified kitten could not be found
405 | Method Not Allowed -- You tried to access a kitten with an invalid method
406 | Not Acceptable -- You requested a format that isn't json
410 | Gone -- The kitten requested has been removed from our servers
418 | I'm a teapot
429 | Too Many Requests -- You're requesting too many kittens! Slow down!
500 | Internal Server Error -- We had a problem with our server. Try again later.
503 | Service Unavailable -- We're temporarially offline for maintanance. Please try again later.

View File

@ -1,26 +0,0 @@
---
weight: 20
title: Feil
---
# Feil
<aside class="notice">Denne seksjonen om feil er lagra i éiga fil, errors.md. DocuAPI let deg dele dokumentasjonen inn i så mange filer som du måtte ynskje. Filene blir henta inn i standard Hugo-rekkjefølgje. Den lettaste måten å styre denne rekkjefølgja er å sette vekt på kvar side, t.d. `weight=10` Sidene med lågast vekt blir vist først.</aside>
Kittn-APIet tek i bruk følgjande feilkodar:
Feilkode | Forklaring
---------- | -------
400 | Bad Request -- Din førespurnad har forbetringspotensiale
401 | Unauthorized -- Feil API-nøkkel
403 | Forbidden -- Denne kattungen er berre tilgjengeleg for administratorar
404 | Not Found -- Denne kattungen vart ikkje funnen
405 | Method Not Allowed -- Du prøvde å få tak i kattungen på ein snodig og ulovleg måte
406 | Not Acceptable -- Du bad om eit format som ikkje er JSON
410 | Gone -- Kattungen har rømt frå serveren.
418 | I'm a teapot
429 | Too Many Requests -- Du spør om for mange kattungar, ta det med ro!
500 | Internal Server Error -- Me har eit problem med serveren. Prøv igjen seinare.
503 | Service Unavailable -- Me er nede for vedlikehald. Prøv igjen seinare.

View File

@ -1,212 +0,0 @@
---
weight: 10
title: API Reference
---
# Introduction
Welcome to the Kittn API! You can use our API to access Kittn API endpoints, which can get information on various cats, kittens, and breeds in our database.
We have language bindings in Shell, Ruby, and Python! You can view code examples in the dark area to the right, and you can switch the programming language of the examples with the tabs in the top right.
**This example API documentation page was created with [DocuAPI](https://github.com/bep/docuapi/), a multilingual documentation theme for the static site generator [Hugo](http://gohugo.io/).**
# Authentication
> To authorize, use this code:
```go
package main
import "github.com/bep/kittn/auth"
func main() {
api := auth.Authorize("meowmeowmeow")
// Just to make it compile
_ = api
}
```
```ruby
require 'kittn'
api = Kittn::APIClient.authorize!('meowmeowmeow')
```
```python
import kittn
api = kittn.authorize('meowmeowmeow')
```
```shell
# With shell, you can just pass the correct header with each request
curl "api_endpoint_here"
-H "Authorization: meowmeowmeow"
```
```javascript
const kittn = require('kittn');
let api = kittn.authorize('meowmeowmeow');
```
> Make sure to replace `meowmeowmeow` with your API key.
Kittn uses API keys to allow access to the API. You can register a new Kittn API key at our [developer portal](http://example.com/developers).
Kittn expects for the API key to be included in all API requests to the server in a header that looks like the following:
`Authorization: meowmeowmeow`
<aside class="notice">
You must replace <code>meowmeowmeow</code> with your personal API key.
</aside>
# Kittens
## Get All Kittens
```go
package main
import "github.com/bep/kittn/auth"
func main() {
api := auth.Authorize("meowmeowmeow")
_ = api.GetKittens()
}
```
```ruby
require 'kittn'
api = Kittn::APIClient.authorize!('meowmeowmeow')
api.kittens.get
```
```python
import kittn
api = kittn.authorize('meowmeowmeow')
api.kittens.get()
```
```shell
curl "http://example.com/api/kittens"
-H "Authorization: meowmeowmeow"
```
```javascript
const kittn = require('kittn');
let api = kittn.authorize('meowmeowmeow');
let kittens = api.kittens.get();
```
> The above command returns JSON structured like this:
```json
[
{
"id": 1,
"name": "Fluffums",
"breed": "calico",
"fluffiness": 6,
"cuteness": 7
},
{
"id": 2,
"name": "Max",
"breed": "unknown",
"fluffiness": 5,
"cuteness": 10
}
]
```
This endpoint retrieves all kittens.
### HTTP Request
`GET http://example.com/api/kittens`
### Query Parameters
Parameter | Default | Description
--------- | ------- | -----------
include_cats | false | If set to true, the result will also include cats.
available | true | If set to false, the result will include kittens that have already been adopted.
<aside class="success">
Remember — a happy kitten is an authenticated kitten!
</aside>
## Get a Specific Kitten
```go
package main
import "github.com/bep/kittn/auth"
func main() {
api := auth.Authorize("meowmeowmeow")
_ = api.GetKitten(2)
}
```
```ruby
require 'kittn'
api = Kittn::APIClient.authorize!('meowmeowmeow')
api.kittens.get(2)
```
```python
import kittn
api = kittn.authorize('meowmeowmeow')
api.kittens.get(2)
```
```shell
curl "http://example.com/api/kittens/2"
-H "Authorization: meowmeowmeow"
```
```javascript
const kittn = require('kittn');
let api = kittn.authorize('meowmeowmeow');
let max = api.kittens.get(2);
```
> The above command returns JSON structured like this:
```json
{
"id": 2,
"name": "Max",
"breed": "unknown",
"fluffiness": 5,
"cuteness": 10
}
```
This endpoint retrieves a specific kitten.
<aside class="warning">Inside HTML code blocks like this one, you can't use Markdown, so use <code>&lt;code&gt;</code> blocks to denote code.</aside>
### HTTP Request
`GET http://example.com/kittens/<ID>`
### URL Parameters
Parameter | Description
--------- | -----------
ID | The ID of the kitten to retrieve

View File

@ -1,211 +0,0 @@
---
weight: 10
title: API
---
# Innleiing
Velkomen skal du vere til Kittn API! Du kan bruke vårt API til å kalle våre Kittn endepunkt. Her kan du hente ut ymse informasjon om kattar, kattungar og ulike rasar frå vår database.
Her finn du kodedøme i Shell, Ruby, Python og Go! Du ser desse døma i det mørke feltet til høgre på skjermen -- og du kan byta programmeringsspråk ved å klikke på menyen oppe til høgre.
**Denne API-dokumentasjonen vart laga med [DocuAPI](https://github.com/bep/docuapi/), eit tema for den statiske nettstadsmakaren [Hugo](http://gohugo.io/).**
# Autentisering
> For å autentisere ein brukar, bruk denne koden:
```go
package main
import "github.com/bep/kittn/auth"
func main() {
api := auth.Authorize("meowmeowmeow")
// Just to make it compile
_ = api
}
```
```ruby
require 'kittn'
api = Kittn::APIClient.authorize!('meowmeowmeow')
```
```python
import kittn
api = kittn.authorize('meowmeowmeow')
```
```shell
# With shell, you can just pass the correct header with each request
curl "api_endpoint_here"
-H "Authorization: meowmeowmeow"
```
```javascript
const kittn = require('kittn');
let api = kittn.authorize('meowmeowmeow');
```
> Gjer vel og erstatt `meowmeowmeow` med din eigen API-nøkkel.
Kittn tek i bruk API-nøklar for å gi tilgang til APIet. Du kan kan registrere deg for å få ein slik nøkkel på vår [utviklarportal](http://example.com/developers).
Kittn forventar at API-nøkkelen er med i alle API-førespurnader til serveren i ein header som ser slik ut:
`Authorization: meowmeowmeow`
<aside class="notice">
Merk: Du må erstatte <code>meowmeowmeow</code> med din personlege nøkkel.</aside>
# Kattungar
## Hent alle kattungane
```go
package main
import "github.com/bep/kittn/auth"
func main() {
api := auth.Authorize("meowmeowmeow")
_ = api.GetKittens()
}
```
```ruby
require 'kittn'
api = Kittn::APIClient.authorize!('meowmeowmeow')
api.kittens.get
```
```python
import kittn
api = kittn.authorize('meowmeowmeow')
api.kittens.get()
```
```shell
curl "http://example.com/api/kittens"
-H "Authorization: meowmeowmeow"
```
```javascript
const kittn = require('kittn');
let api = kittn.authorize('meowmeowmeow');
let kittens = api.kittens.get();
```
> Programmet over gir ein JSON-struktur som ser slik ut:
```json
[
{
"id": 1,
"name": "Fluffums",
"breed": "calico",
"fluffiness": 6,
"cuteness": 7
},
{
"id": 2,
"name": "Max",
"breed": "unknown",
"fluffiness": 5,
"cuteness": 10
}
]
```
Dette endepunktet leverer alle kattungar.
### HTTP-førespurnad
`GET http://example.com/api/kittens`
### Query-parametrar
Parameter | Standardverdi | Skildring
--------- | ------- | -----------
include_cats | false | Set til true for å få alle kattar.
available | true | Set til false for å ta med kattar som allereie er blitt adoptert vekk.
<aside class="success">
Hugs — ein lukkeleg kattunge er ein autentisert kattunge!
</aside>
## Hent éin kattunge
```go
package main
import "github.com/bep/kittn/auth"
func main() {
api := auth.Authorize("meowmeowmeow")
_ = api.GetKitten(2)
}
```
```ruby
require 'kittn'
api = Kittn::APIClient.authorize!('meowmeowmeow')
api.kittens.get(2)
```
```python
import kittn
api = kittn.authorize('meowmeowmeow')
api.kittens.get(2)
```
```shell
curl "http://example.com/api/kittens/2"
-H "Authorization: meowmeowmeow"
```
```javascript
const kittn = require('kittn');
let api = kittn.authorize('meowmeowmeow');
let max = api.kittens.get(2);
```
> Programmet over gir ein JSON-struktur som ser slik ut:
```json
{
"id": 2,
"name": "Max",
"breed": "unknown",
"fluffiness": 5,
"cuteness": 10
}
```
Dette endepunktet hentar ut éin spesifikk kattunge.
<aside class="warning">Inne i HTML-blokker som denne så kan du ikkje bruke Markdown. Bruk <code>&lt;code&gt;</code> for å markere kjeldekode.</aside>
### HTTP-førespurnad
`GET http://example.com/kittens/<ID>`
### URL-parametrar
Parameter | Skildring
--------- | -----------
ID | IDen til kattungen du ynskjer å hente

View File

@ -1,12 +0,0 @@
{{ with getenv "ADD_GA" }}
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-52478213-11', 'auto');
ga('send', 'pageview');
</script>
{{ end }}

View File

@ -1,7 +0,0 @@
{{ if getenv "REPOSITORY_URL" -}}
<div style="margin-left: 20px; margin-top: 20px">
<a href="https://www.netlify.com">
<img src="https://www.netlify.com/img/global/badges/netlify-dark.svg"/>
</a>
</div>
{{ end }}

View File

@ -1,4 +0,0 @@
/*
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block

View File

@ -1,8 +0,0 @@
- id: translations
translation:
one: "Translation"
other: "Translations"
# Search label
- id: search
translation: "Search"

View File

@ -1,8 +0,0 @@
- id: translations
translation:
one: "Omsetjing"
other: "Omsetjingar"
# Search label
- id: search
translation: "Søk"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 235 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 KiB

View File

@ -1,3 +0,0 @@
{{define "main"}}
<h2>Page Not Found!</h2>
{{end}}

View File

@ -1,69 +0,0 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>{{ .Title }}</title>
{{ partial "styles.html" . }}
{{ partial "js.html" . }}
{{ partial "hook_head_end.html" . }}
</head>
<body class="index" data-languages="{{ with .Site.Params.language_tabs }}[{{ range $i,$e := . }}{{- if $i -}}, {{ end -}}{{ printf " %q " $e.key }}{{end}}]{{ end }}">
<a href="#" id="nav-button">
<span>
NAV
<img src='{{ relURL "slate/images/navbar.png" }}'/>
</span>
</a>
<div class="tocify-wrapper">
{{ partial "hook_left_sidebar_start.html" . }}
{{ partial "hook_left_sidebar_logo.html" . }}
{{ with .Site.Params.language_tabs }}
<div class="lang-selector">
{{ range . }}
<a href="#" data-language-name="{{ .key }}">{{ .name }}</a>
{{ end }}
</div>
{{ end }}
{{ if .Site.Params.search }}
<div class="search">
<input type="text" class="search" id="input-search" placeholder='{{ T "search" . }}'>
</div>
<ul class="search-results"></ul>
{{ end }}
<div id="toc">
</div>
{{ if .IsTranslated }}
<div class="toc-footer">
<h3 class="translations-title">{{ T "translations" (len .Translations ) }}</h3>
{{ partial "translations.html" . }}
</div>
{{ end }}
{{ with .Site.Params.toc_footers }}
<ul class="toc-footer">
{{ range . }}
<li>{{ . | markdownify }}</li>
{{ end}}
</ul>
{{ end}}
{{ partial "hook_left_sidebar_end.html" . }}
</div>
<div class="page-wrapper">
<div class="dark-box"></div>
<div class="content">
{{block "main" .}}This is the main content.{{end}}
</div>
<div class="dark-box">
{{ with .Site.Params.language_tabs }}
<div class="lang-selector">
{{ range . }}
<a href="#" data-language-name="{{ .key }}">{{ .name }}</a>
{{ end }}
</div>
{{ end }}
</div>
</div>
{{ partial "hook_body_end.html" . }}
</body>
</html>

View File

@ -1,5 +0,0 @@
{{define "main"}}
{{ range .Data.Pages }}
{{ .Content }}
{{ end }}
{{end}}

View File

@ -1 +0,0 @@
<img src='{{ relURL "images/logo.png" }}' />

View File

@ -1,5 +0,0 @@
{{ if .Param "search" }}
<script src='{{ relURL "slate/javascripts/all.js" }}'></script>
{{ else }}
<script src='{{ relURL "slate/javascripts/all_nosearch.js" }}'></script>
{{ end }}

View File

@ -1,3 +0,0 @@
<link href='{{ relURL "slate/stylesheets/monokai.css" }}' rel="stylesheet" media="screen" />
<link href='{{ relURL "slate/stylesheets/screen.css" }}' rel="stylesheet" media="screen" />
<link href='{{ relURL "slate/stylesheets/print.css" }}' rel="stylesheet" media="print" />

View File

@ -1,7 +0,0 @@
{{ if .IsTranslated }}
<ul>
{{ range $i, $e := .Translations }}
<li><a href="{{ .Permalink }}">{{ $e.Language.LanguageName }}</a></li>
{{ end}}
</ul>
{{ end }}

View File

@ -1 +0,0 @@
Pygments==2.0.2

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,14 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Generated by IcoMoon</metadata>
<defs>
<font id="slate" horiz-adv-x="1024">
<font-face units-per-em="1024" ascent="960" descent="-64" />
<missing-glyph horiz-adv-x="1024" />
<glyph unicode="&#x20;" d="" horiz-adv-x="512" />
<glyph unicode="&#xe600;" d="M438.857 877.714q119.429 0 220.286-58.857t159.714-159.714 58.857-220.286-58.857-220.286-159.714-159.714-220.286-58.857-220.286 58.857-159.714 159.714-58.857 220.286 58.857 220.286 159.714 159.714 220.286 58.857zM512 165.143v108.571q0 8-5.143 13.429t-12.571 5.429h-109.714q-7.429 0-13.143-5.714t-5.714-13.143v-108.571q0-7.429 5.714-13.143t13.143-5.714h109.714q7.429 0 12.571 5.429t5.143 13.429zM510.857 361.714l10.286 354.857q0 6.857-5.714 10.286-5.714 4.571-13.714 4.571h-125.714q-8 0-13.714-4.571-5.714-3.429-5.714-10.286l9.714-354.857q0-5.714 5.714-10t13.714-4.286h105.714q8 0 13.429 4.286t6 10z" />
<glyph unicode="&#xe602;" d="M585.143 164.571v91.429q0 8-5.143 13.143t-13.143 5.143h-54.857v292.571q0 8-5.143 13.143t-13.143 5.143h-182.857q-8 0-13.143-5.143t-5.143-13.143v-91.429q0-8 5.143-13.143t13.143-5.143h54.857v-182.857h-54.857q-8 0-13.143-5.143t-5.143-13.143v-91.429q0-8 5.143-13.143t13.143-5.143h256q8 0 13.143 5.143t5.143 13.143zM512 676.571v91.429q0 8-5.143 13.143t-13.143 5.143h-109.714q-8 0-13.143-5.143t-5.143-13.143v-91.429q0-8 5.143-13.143t13.143-5.143h109.714q8 0 13.143 5.143t5.143 13.143zM877.714 438.857q0-119.429-58.857-220.286t-159.714-159.714-220.286-58.857-220.286 58.857-159.714 159.714-58.857 220.286 58.857 220.286 159.714 159.714 220.286 58.857 220.286-58.857 159.714-159.714 58.857-220.286z" />
<glyph unicode="&#xe606;" d="M733.714 531.428q0 16-10.286 26.286l-52 51.429q-10.857 10.857-25.714 10.857t-25.714-10.857l-233.143-232.571-129.143 129.143q-10.857 10.857-25.714 10.857t-25.714-10.857l-52-51.429q-10.286-10.286-10.286-26.286 0-15.429 10.286-25.714l206.857-206.857q10.857-10.857 25.714-10.857 15.429 0 26.286 10.857l310.286 310.286q10.286 10.286 10.286 25.714zM877.714 438.857q0-119.429-58.857-220.286t-159.714-159.714-220.286-58.857-220.286 58.857-159.714 159.714-58.857 220.286 58.857 220.286 159.714 159.714 220.286 58.857 220.286-58.857 159.714-159.714 58.857-220.286z" />
<glyph unicode="&#xe607;" d="M658.286 475.428q0 105.714-75.143 180.857t-180.857 75.143-180.857-75.143-75.143-180.857 75.143-180.857 180.857-75.143 180.857 75.143 75.143 180.857zM950.857 0q0-29.714-21.714-51.429t-51.429-21.714q-30.857 0-51.429 21.714l-196 195.429q-102.286-70.857-228-70.857-81.714 0-156.286 31.714t-128.571 85.714-85.714 128.571-31.714 156.286 31.714 156.286 85.714 128.571 128.571 85.714 156.286 31.714 156.286-31.714 128.571-85.714 85.714-128.571 31.714-156.286q0-125.714-70.857-228l196-196q21.143-21.143 21.143-51.429z" horiz-adv-x="951" />
</font></defs></svg>

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 B

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
.highlight pre{background-color:#272822}.highlight .hll{background-color:#272822}.highlight .c{color:#75715e}.highlight .err{color:#960050;background-color:#1e0010}.highlight .k{color:#66d9ef}.highlight .l{color:#ae81ff}.highlight .n{color:#f8f8f2}.highlight .o{color:#f92672}.highlight .p{color:#f8f8f2}.highlight .cm{color:#75715e}.highlight .cp{color:#75715e}.highlight .c1{color:#75715e}.highlight .cs{color:#75715e}.highlight .ge{font-style:italic}.highlight .gs{font-weight:bold}.highlight .kc{color:#66d9ef}.highlight .kd{color:#66d9ef}.highlight .kn{color:#f92672}.highlight .kp{color:#66d9ef}.highlight .kr{color:#66d9ef}.highlight .kt{color:#66d9ef}.highlight .ld{color:#e6db74}.highlight .m{color:#ae81ff}.highlight .s{color:#e6db74}.highlight .na{color:#a6e22e}.highlight .nb{color:#f8f8f2}.highlight .nc{color:#a6e22e}.highlight .no{color:#66d9ef}.highlight .nd{color:#a6e22e}.highlight .ni{color:#f8f8f2}.highlight .ne{color:#a6e22e}.highlight .nf{color:#a6e22e}.highlight .nl{color:#f8f8f2}.highlight .nn{color:#f8f8f2}.highlight .nx{color:#a6e22e}.highlight .py{color:#f8f8f2}.highlight .nt{color:#f92672}.highlight .nv{color:#f8f8f2}.highlight .ow{color:#f92672}.highlight .w{color:#f8f8f2}.highlight .mf{color:#ae81ff}.highlight .mh{color:#ae81ff}.highlight .mi{color:#ae81ff}.highlight .mo{color:#ae81ff}.highlight .sb{color:#e6db74}.highlight .sc{color:#e6db74}.highlight .sd{color:#e6db74}.highlight .s2{color:#e6db74}.highlight .se{color:#ae81ff}.highlight .sh{color:#e6db74}.highlight .si{color:#e6db74}.highlight .sx{color:#e6db74}.highlight .sr{color:#e6db74}.highlight .s1{color:#e6db74}.highlight .ss{color:#e6db74}.highlight .bp{color:#f8f8f2}.highlight .vc{color:#f8f8f2}.highlight .vg{color:#f8f8f2}.highlight .vi{color:#f8f8f2}.highlight .il{color:#ae81ff}.highlight .gu{color:#75715e}.highlight .gd{color:#f92672}.highlight .gi{color:#a6e22e}

View File

@ -1 +0,0 @@
/*! normalize.css v3.0.2 | MIT License | git.io/normalize */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:1px 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{-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"]{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;-moz-box-sizing:content-box;-webkit-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}.content h1,.content h2,.content h3,.content h4,body{font-family:"Helvetica Neue", Helvetica, Arial, "Microsoft Yahei","微软雅黑", STXihei, "华文细黑", sans-serif;font-size:13px}.content h1,.content h2,.content h3,.content h4{font-weight:bold}.content pre,.content code{font-family:Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, serif;font-size:12px;line-height:1.5}.content pre,.content code{word-break:break-all;hyphens:auto}@font-face{font-family:'slate';src:font-url("slate.eot?-syv14m");src:font-url("slate.eot?#iefix-syv14m") format("embedded-opentype"),font-url("slate.woff2?-syv14m") format("woff2"),font-url("slate.woff?-syv14m") format("woff"),font-url("slate.ttf?-syv14m") format("truetype"),font-url("slate.svg?-syv14m#slate") format("svg");font-weight:normal;font-style:normal}.content aside.warning:before,.content aside.notice:before,.content aside.success:before{font-family:'slate';speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1}.content aside.warning:before{content:"\e600"}.content aside.notice:before{content:"\e602"}.content aside.success:before{content:"\e606"}.tocify,.toc-footer,.lang-selector,.search,#nav-button{display:none}.tocify-wrapper>img{margin:0 auto;display:block}.content{font-size:12px}.content pre,.content code{border:1px solid #999;border-radius:5px;font-size:0.8em}.content pre code{border:0}.content pre{padding:1.3em}.content code{padding:0.2em}.content table{border:1px solid #999}.content table tr{border-bottom:1px solid #999}.content table td,.content table th{padding:0.7em}.content p{line-height:1.5}.content a{text-decoration:none;color:#000}.content h1{font-size:2.5em;padding-top:0.5em;padding-bottom:0.5em;margin-top:1em;margin-bottom:21px;border:2px solid #ccc;border-width:2px 0;text-align:center}.content h2{font-size:1.8em;margin-top:2em;border-top:2px solid #ccc;padding-top:0.8em}.content h1+h2,.content h1+div+h2{border-top:none;padding-top:0;margin-top:0}.content h3,.content h4{font-size:0.8em;margin-top:1.5em;margin-bottom:0.8em;text-transform:uppercase}.content h5,.content h6{text-transform:uppercase}.content aside{padding:1em;border:1px solid #ccc;border-radius:5px;margin-top:1.5em;margin-bottom:1.5em;line-height:1.6}.content aside:before{vertical-align:middle;padding-right:0.5em;font-size:14px}

File diff suppressed because one or more lines are too long

View File

@ -1,17 +0,0 @@
name = "DocuAPI"
license = "Apache-2.0"
licenselink = "https://github.com/bep/docuapi/blob/master/LICENSE.md"
description = "Beautiful documentation for your API."
homepage = "https://github.com/bep/docuapi"
tags = ["Documentation", "API", "Docs", "Responsive", "Multilingual"]
features = ["Documentation", "Multilingual"]
min_version = 0.17
[author]
name = "Bjørn Erik Pedersen"
homepage = "http://bep.is"
[original]
name = "Slate"
homepage = "https://github.com/lord/slate"
repo = "https://github.com/lord/slate"

View File

@ -1,7 +1,7 @@
.. _cement.core.arg:
:mod:`cement.core.arg`
----------------------
======================
.. automodule:: cement.core.arg
:members:

View File

@ -1,9 +0,0 @@
.. _cement.ext.ext_alarm:
:mod:`cement.ext.ext_alarm`
---------------------------
.. automodule:: cement.ext.ext_alarm
:members:
:private-members:
:show-inheritance:

View File

@ -1,38 +1,33 @@
.. note:: This documentation is strictly for API reference. For more complete
developer documentation, please visit the official site
http://builtoncement.com.
Cement Framework API Reference
==============================
.. _api-core:
Core Modules
------------
============
.. toctree::
:maxdepth: 1
:maxdepth: 1
core/arg
core/backend
core/cache
core/config
core/controller
core/exc
core/extension
core/foundation
core/handler
core/hook
core/log
core/mail
core/meta
core/output
core/plugin
core/arg
core/backend
core/cache
core/config
core/controller
core/exc
core/extension
core/foundation
core/handler
core/hook
core/log
core/mail
core/meta
core/output
core/plugin
.. _api-utils:
Utility Modules
---------------
===============
.. toctree::
:maxdepth: 1
@ -42,10 +37,9 @@ Utility Modules
utils/misc
utils/test
.. _api-ext:
Extension Modules
-----------------
=================
.. toctree::
:maxdepth: 1

View File

@ -13,14 +13,66 @@
import os
import sys
import guzzle_sphinx_theme
import pypandoc
import recommonmark
from recommonmark.transform import AutoStructify
def pandoc_process(app, what, name, obj, options, lines):
if not lines:
return
input_format = app.config.pandoc_use_parser
data = '\n'.join(lines)
data = data.encode('utf-8')
# data = str(pypandoc.convert(data, 'rst', format=input_format),
# encoding='utf-8')
data = pypandoc.convert(data, 'rst', format=input_format)
# Sphinx expects `lines` to be edited in place, so we have to replace it
# like this.
new_lines = data.split('\n')
del lines[:]
lines.extend(new_lines)
html_theme_path = guzzle_sphinx_theme.html_theme_path()
html_theme = 'guzzle_sphinx_theme'
# Guzzle theme options (see theme.conf for more information)
html_theme_options = {
# Set the path to a special layout to include for the homepage
# "index_template": "special_index.html",
# Set the name of the project to appear in the left sidebar.
# "project_nav_name": "Cement",
# Set your Disqus short name to enable comments
# "disqus_comments_shortname": "my_disqus_comments_short_name",
# Set you GA account ID to enable tracking
# "google_analytics_account": "my_ga_account",
# Path to a touch icon
# "touch_icon": "",
# Specify a base_url used to generate sitemap.xml links. If not
# specified, then no sitemap will be built.
# "base_url": ""
# Allow a separate homepage from the master_doc
"homepage": "index",
# Allow the project link to be overriden to a custom URL.
"projectlink": "http://builtoncement.com",
}
sys.path.insert(0, os.path.abspath('../cement/'))
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
#on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
if not on_rtd: # only import and set the theme if we're building docs locally
import sphinx_rtd_theme
html_theme = 'sphinx_rtd_theme'
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
#if not on_rtd: # only import and set the theme if we're building docs locally
# import sphinx_rtd_theme
# html_theme = 'sphinx_rtd_theme'
# html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
# If we dont' prep an app, then we'll get runtime errors
from cement.utils import test, version
@ -50,9 +102,9 @@ class Mock(object):
return Mock()
MOCK_MODULES = [
'nose',
'pylibmc',
'yaml',
'nose',
'pylibmc',
'yaml',
'tabulate',
'pystache', 'pystache.renderer',
'colorlog',
@ -76,9 +128,14 @@ sys.modules.update((mod_name, Mock()) for mod_name in MOCK_MODULES)
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.extlinks',
'sphinx.ext.intersphinx'
'sphinx.ext.intersphinx',
'sphinx.ext.napoleon',
]
source_parsers = {
'.md': 'recommonmark.parser.CommonMarkParser',
}
extlinks = {
'issue' : ('https://github.com/datafolklabs/cement/issues/%s', 'Issue #'),
'pr' : ('https://github.com/datafolklabs/cement/pull/%s', 'PR #'),
@ -98,7 +155,7 @@ source_suffix = ['.rst', '.md']
master_doc = 'index'
# General information about the project.
project = u'Cement Framework'
project = u'Cement API Reference'
copyright = u'2009-2017, Data Folk Labs, LLC'
# The version info for the project you're documenting, acts as replacement for
@ -273,3 +330,16 @@ man_pages = [
('index', 'cement', u'Cement Framework',
[u'Data Folk Labs, LLC'], 1)
]
# At the bottom of conf.py
def setup(app):
app.add_config_value('recommonmark_config', {
# 'url_resolver': lambda url: github_doc_root + url,
'auto_toc_tree_section': 'Contents',
'enable_auto_toc_tree': True,
'enable_auto_doc_ref': True,
}, True)
app.add_transform(AutoStructify)
app.add_config_value('pandoc_use_parser', 'markdown', True)
app.connect('autodoc-process-docstring', pandoc_process)

View File

@ -1,7 +1,4 @@
Cement Framework
================
.. note:: This documentation is strictly for API reference. For more complete
developer documentation, please visit the official site
http://builtoncement.com.
@ -10,19 +7,10 @@ Cement Framework
become Cement 3. It is guaranteed to be broken! Please use Cement 2 in
production until stable/3.0.0 is released.
Cement is an advanced CLI Application Framework for Python. Its goal is to
introduce a standard, and feature-full platform for both simple and complex
command line applications as well as support rapid development needs without
sacrificing quality. Cement is flexible, and it's use cases span from the
simplicity of a micro-framework to the complexity of a mega-framework.
Whether it's a single file script, or a multi-tier application, Cement is the
foundation you've been looking for.
Documentation
-------------
API Reference
=============
.. toctree::
:maxdepth: 2
api/index
license

View File

@ -6,7 +6,9 @@ pep8
autopep8
flake8
mock
sphinx_rtd_theme
guzzle_sphinx_theme
recommonmark
sphinxcontrib-napoleon
# Required for optional extensions
pystache