diff --git a/.github/workflows/webviz-config.yml b/.github/workflows/webviz-config.yml
index fc4ee34a..fd85563d 100644
--- a/.github/workflows/webviz-config.yml
+++ b/.github/workflows/webviz-config.yml
@@ -36,6 +36,11 @@ jobs:
with:
python-version: ${{ matrix.python-version }}
+ - name: 📦 Install npm dependencies
+ run: |
+ npm ci --ignore-scripts
+ npm run postinstall
+
- name: 📦 Install webviz-config with dependencies
run: |
pip install 'pandas==${{ matrix.pandas-version }}'
@@ -65,9 +70,7 @@ jobs:
webviz certificate
webviz preferences --theme default
pytest ./tests --headless --forked
- pushd ./docs
- python build_docs.py
- popd
+ webviz docs --portable ./docs_build --skip-open
- name: 🚢 Build and deploy Python package
if: github.event_name == 'release' && matrix.python-version == '3.6' && matrix.pandas-version == '1.*'
@@ -75,6 +78,7 @@ jobs:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.pypi_webviz_token }}
run: |
+ export SETUPTOOLS_SCM_PRETEND_VERSION=${GITHUB_REF//refs\/tags\//}
python -m pip install --upgrade setuptools wheel twine
python setup.py sdist bdist_wheel
twine upload dist/*
@@ -82,7 +86,7 @@ jobs:
- name: 📚 Update GitHub pages
if: github.event_name != 'schedule' && github.ref == 'refs/heads/master' && matrix.python-version == '3.6' && matrix.pandas-version == '1.*'
run: |
- cp -R ./docs/_build ../_build
+ cp -R ./docs_build ../docs_build
git config --local user.email "webviz-github-action"
git config --local user.name "webviz-github-action"
@@ -91,7 +95,7 @@ jobs:
git clean -f -f -d -x
git rm -r *
- cp -R ../_build/* .
+ cp -R ../docs_build/* .
git add .
diff --git a/.gitignore b/.gitignore
index dfd95b6c..3b8b674e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,3 +11,9 @@ venv
.DS_Store
dist
build
+webviz_config/_docs/static/fonts
+webviz_config/_docs/static/INTRODUCTION.md
+webviz_config/_docs/static/*.js
+webviz_config/_docs/static/*.css
+!webviz_config/_docs/static/webviz-doc.js
+!webviz_config/_docs/static/webviz-doc.css
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 5fc0389b..e12beca0 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -509,15 +509,55 @@ black --check webviz_config tests
## Build documentation
-End-user documentation (i.e. YAML configuration file) be created
-after installation by
+`webviz-config` can automatically build documentation for all installed plugins. E.g.
+the end user can get an overview of all installed plugins, and their arguments, by
+running
+```bash
+webviz docs
+```
+in the terminal. Behind the scenes, `webviz-config` will then create a
+[`docsify`](https://github.com/docsifyjs/docsify) setup and open it `localhost`.
+The setup can also be deployed to e.g. GitHub Pages directly. To store the documentation
+output run
```bash
-pip install .[tests] # if not already done
-cd ./docs
-python ./build_docs.py
+webviz docs --portable ./built_docs --skip-open
+```
+The `--skip-open` argument is useful in a CI/CD setting, to prevent `webviz-config`
+from automatically trying to open the created documentation in the browser.
+
+### Improve plugin documentation
+
+Auto-built `webviz` documentation will:
+- Find all installed plugins.
+- Group them according to top package name.
+- Show a `YAML` snippet with the plugin argument options.
+ - Arguments with default values will be presented with the default value, and be marked as optional.
+ - If an argument has a type annotation, that will be included in the documentation.
+
+In addition, if the plugin class has a docstring, the content in the docstring will
+be used as a short introduction to the plugin. If the docstring has several parts,
+when split by a line containing only `---`, they will be used as follows:
+1. First part is the introduction to the plugin.
+2. Second part is a more detailed explanation of the plugin arguments.
+3. Third part is information regarding plugin data input. E.g assumptions,
+prerequisites and/or required/assumed data format.
+
+Since `docsify` is used behind the scenes, you can create information boxes, warning boxes
+and use GitHub emojis :bowtie: in the plugin docstring.
+See [`docsify` documentation](https://docsify.js.org/#/) for details.
+
+[KaTeX](https://katex.org/) is also used behind the scenes, meaning that you can add
+math (TeX syntax) to your docstrings and get it rendered in the auto-built
+documentation. Remember that `\` is an escape character in Python, i.e. either
+escape it (`\\`) or use raw strings:
+```python
+class HistoryMatch(WebvizPluginABC):
+ r"""This is a docstring with some inline math $\alpha$ and some block math:
+
+$$\alpha = \frac{\beta}{\gamma}$$
+"""
```
-Officially updated built end-user documentation (i.e. information to the
-person setting up the configuration file) is
-[hosted here on github](https://equinor.github.io/webviz-config/).
+Example of auto-built documentation for `webviz-config` can be seen
+[here on github](https://equinor.github.io/webviz-config/).
diff --git a/INTRODUCTION.md b/INTRODUCTION.md
new file mode 100644
index 00000000..65081e5c
--- /dev/null
+++ b/INTRODUCTION.md
@@ -0,0 +1,101 @@
+# Webviz introduction
+
+### Fundamental configuration
+
+A configuration consists of some mandatory properties, e.g. app title,
+and one or more pages. A page has a title and some content.
+Each page can contain as many plugins as you want.
+
+Plugins represent predefined content, which can take one or more arguments.
+Lists and descriptions of installed plugins can be found on the other subpages.
+
+Content which is not plugins is interpreted as text paragraphs.
+
+A simple example configuration:
+```yaml
+# This is a webviz configuration file example.
+# The configuration files use the YAML standard (https://en.wikipedia.org/wiki/YAML).
+
+title: Reek Webviz Demonstration
+
+pages:
+
+ - title: Front page
+ content:
+ - BannerImage:
+ image: ./example_banner.png
+ title: My banner image
+ - Webviz created from a configuration file.
+
+ - title: Markdown example
+ content:
+ - Markdown:
+ markdown_file: ./example-markdown.md
+```
+
+### Command line usage
+
+#### Get documentation
+
+You can always run `webviz --help` to see available command line options.
+To see command line options on a subcommand, run e.g. `webviz build --help`.
+
+:books: To open the `webviz` documentation on all installed plugins, run `webviz docs`.
+
+#### Portable vs. non-portable
+
+Assuming you have a configuration file `your_config.yml`,
+there are two main usages of `webviz`:
+
+```bash
+webviz build your_config.yml
+```
+and
+```bash
+webviz build your_config.yml --portable ./some_output_folder
+python ./some_output_folder/webviz_app.py
+```
+
+**Portable**
+
+The portable way is useful when one or more plugins included in the configuration need to do
+some time-consuming data aggregation on their own, before presenting it to the user.
+The time-consuming part will then be done in the `build` step, and you can run your
+created application as many time as you want afterwards, with as little waiting
+time as possible.
+
+The `--portable` way also has the benefit of creating a :whale: Docker setup for your
+application - ready to be deployed to e.g. a cloud provider.
+
+**Non-portable**
+
+Non-portable is the easiest way if none of the plugins
+have time-consuming data aggregration to do.
+
+A feature in Dash, used by `webviz` is [hot reload](https://community.plot.ly/t/announcing-hot-reload/14177).
+When the Dash Python code file is saved, the content seen in the web browser is
+automatically reloaded (no need for localhost server restart). This feature is passed on to
+the Webviz configuration utility, meaning that if you run
+```bash
+webviz build ./examples/basic_example.yaml
+```
+and then modify `./examples/basic_example.yaml` while the Webviz application is
+still running, a hot reload will occur.
+
+#### Localhost certificate
+
+For quick local analysis, `webviz-config` uses `https` and runs on `localhost`.
+In order to create your personal :lock: `https` certificate (only valid for `localhost`), run
+```bash
+webviz certificate --auto-install
+```
+Certificate installation guidelines will be given when running the command.
+
+#### User preferences
+
+You can set preferred :rainbow: theme and/or :earth_africa: browser, such that `webviz` remembers it for later
+runs. E.g.
+
+```bash
+webviz preferences --theme equinor --browser firefox
+```
diff --git a/README.md b/README.md
index 7658633f..26c5cb10 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-
+
Democratizing Python web applications
@@ -42,21 +42,21 @@ Example configuration file and information about the standard plugins can be see
### Installation
-The simplest way of installing `webviz-config` is to run
+The recommended and simplest way of installing `webviz-config` is to run
```bash
pip install webviz-config
```
-If you want to download the latest source code and install it manually you
+If you want to develop `webviz-config` and install the latest source code manually you
+can do something along the lines of:
can run
```bash
git clone git@github.com:equinor/webviz-config.git
cd ./webviz-config
-pip install .
+npm ci --ignore-scripts && npm run postinstall
+pip install -e .
```
-### Usage
-
After installation, there is a console script named `webviz` available. You can test the installation by using the provided test
configuration file,
```bash
@@ -74,28 +74,11 @@ The optional arguments can be seen when running
```bash
webviz --help
```
-For example will
-```bash
-webviz build ./examples/basic_example.yaml --portable ./my_portable_app
-```
-create a portable instance (with corresponding Dockerfile) and store it in the provided folder.
-A feature in Dash is [hot reload](https://community.plot.ly/t/announcing-hot-reload/14177).
-When the Dash Python code file is saved, the content seen in the web browser is
-automatically reloaded (no need for localhost server restart). This feature is passed on to
-the Webviz configuration utility, meaning that if the user runs
-```bash
-webviz build ./examples/basic_example.yaml
-```
-and then modifies `./examples/basic_example.yaml` while the Webviz application is
-still running, a hot reload will occur.
+### Usage
-For quick local analysis, `webviz-config` uses `https` and runs on `localhost`.
-In order to create your personal `https` certificate (only valid for `localhost`), run
-```bash
-webviz certificate --auto-install
-```
-Certificate installation guidelines will be given when running the command.
+See [the introduction](./INTRODUCTION.md) page for information on how you
+create a `webviz` configuration file and use it.
### Creating new plugins
diff --git a/docs/.gitignore b/docs/.gitignore
deleted file mode 100644
index 8d2ac5c4..00000000
--- a/docs/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-node_modules
-_build
diff --git a/docs/assets/webviz_doc.css b/docs/assets/webviz_doc.css
deleted file mode 100644
index 5075391b..00000000
--- a/docs/assets/webviz_doc.css
+++ /dev/null
@@ -1,50 +0,0 @@
-body {
- background-image: linear-gradient(150deg, rgba(255,255,255), rgba(240,240,240));
-}
-
-pre {
- border: 1px solid grey;
-}
-
-hr {
- margin-top: 20px;
- margin-bottom: 20px;
- border: 1px solid rgba(0, 0, 0, 0.1);
-}
-
-div.container {
- width: 80%;
- margin: 0 auto;
- padding: 15px;
-}
-
-.hljs {
- display: block;
- overflow-x: auto;
- padding: 1.5em;
- color: #243746;
- background: rgb(250, 250, 250);
-}
-
-.hljs-comment,
-.hljs-quote {
- color: rgb(100, 100, 100);
- font-style: italic;
-}
-
-.hljs-number,
-.hljs-literal,
-.hljs-variable {
- color: #007079;
-}
-
-.hljs-string {
- color: #7d0023;
-}
-
-.hljs-tag,
-.hljs-name,
-.hljs-attribute {
- color: #d5EAF4;
- font-weight: normal;
-}
diff --git a/docs/build_docs.py b/docs/build_docs.py
deleted file mode 100644
index f7e50351..00000000
--- a/docs/build_docs.py
+++ /dev/null
@@ -1,130 +0,0 @@
-"""Builds automatic documentation of the installed webviz config plugins.
-The documentation is designed to be used by the YAML configuration file end
-user. Sphinx has not been used due to
-
- 1) Sphinx is geared towards Python end users, and templateing of apidoc output
- is not yet supported (https://github.com/sphinx-doc/sphinx/issues/3545).
-
- 2) It is a small problem to be solved, and most of the Sphinx machinery
- is not needed.
-
-Overall workflow is:
- * Finds all installed plugins.
- * Automatically reads docstring and __init__ function signature (both
- argument names and which arguments have default values).
- * Output the extracted plugin information in html using jinja2.
-"""
-
-import shutil
-import inspect
-import pathlib
-from importlib import import_module
-from collections import defaultdict
-import jinja2
-from markdown import markdown
-import webviz_config.plugins
-from webviz_config._config_parser import SPECIAL_ARGS
-
-SCRIPT_DIR = pathlib.Path(__file__).resolve().parent
-BUILD_DIR = SCRIPT_DIR / "_build"
-TEMPLATE_FILE = SCRIPT_DIR / "templates" / "index.html.jinja2"
-EXAMPLE = SCRIPT_DIR / ".." / "examples" / "basic_example.yaml"
-
-
-def escape_all(input_string):
- """Escapes any html or utf8 character in the given string.
- """
-
- no_html = jinja2.escape(input_string)
- no_utf8 = no_html.encode("ascii", "xmlcharrefreplace").decode()
- pass_through = jinja2.Markup(no_utf8)
- return pass_through
-
-
-def convert_docstring(doc):
- """Convert docstring to markdown.
- """
-
- return "" if doc is None else markdown(doc, extensions=["fenced_code"])
-
-
-def get_plugin_documentation():
- """Get all installed plugins, and document them by grabbing docstring
- and input arguments / function signature.
- """
-
- plugins = inspect.getmembers(webviz_config.plugins, inspect.isclass)
-
- plugin_doc = []
-
- for plugin in plugins:
- reference = plugin[1]
-
- plugin_info = {}
-
- plugin_info["name"] = plugin[0]
- plugin_info["doc"] = convert_docstring(reference.__doc__)
-
- argspec = inspect.getfullargspec(reference.__init__)
- plugin_info["args"] = [
- arg for arg in argspec.args if arg not in SPECIAL_ARGS
- ]
-
- plugin_info["values"] = defaultdict(lambda: "some value")
-
- if argspec.defaults is not None:
- for arg, default in dict(
- zip(reversed(argspec.args), reversed(argspec.defaults))
- ).items():
- plugin_info["values"][
- arg
- ] = f"{default} # Optional (default value shown here)."
-
- module = inspect.getmodule(reference)
- plugin_info["module"] = module.__name__
-
- package = inspect.getmodule(module).__package__
- plugin_info["package"] = package
- plugin_info["package_doc"] = convert_docstring(
- import_module(package).__doc__
- )
-
- if not plugin_info["name"].startswith("Example"):
- plugin_doc.append(plugin_info)
-
- # Sort the plugins by package:
-
- package_ordered = defaultdict(lambda: {"plugins": []})
-
- for plugin in sorted(plugin_doc, key=lambda x: (x["module"], x["name"])):
- package = plugin["package"]
- package_ordered[package]["plugins"].append(plugin)
- package_ordered[package]["doc"] = plugin["package_doc"]
-
- return package_ordered
-
-
-def get_basic_example():
- with open(EXAMPLE) as fh:
- return escape_all(fh.read())
-
-
-if __name__ == "__main__":
-
- template_data = {
- "packages": get_plugin_documentation(),
- "basic_example": get_basic_example(),
- }
-
- with open(TEMPLATE_FILE) as fh:
- template = jinja2.Template(fh.read())
-
- if BUILD_DIR.exists():
- shutil.rmtree(BUILD_DIR)
-
- shutil.copytree(SCRIPT_DIR / "assets", BUILD_DIR / "assets")
-
- with open(BUILD_DIR / "index.html", "w") as fh:
- fh.write(template.render(template_data))
-
- print(f"Output available in {BUILD_DIR}")
diff --git a/docs/package-lock.json b/docs/package-lock.json
deleted file mode 100644
index 32a314f9..00000000
--- a/docs/package-lock.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "requires": true,
- "lockfileVersion": 1,
- "dependencies": {
- "highlight.js": {
- "version": "9.14.2",
- "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.14.2.tgz",
- "integrity": "sha512-Nc6YNECYpxyJABGYJAyw7dBAYbXEuIzwzkqoJnwbc1nIpCiN+3ioYf0XrBnLiyyG0JLuJhpPtt2iTSbXiKLoyA=="
- }
- }
-}
diff --git a/docs/package.json b/docs/package.json
deleted file mode 100644
index 87322c5d..00000000
--- a/docs/package.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "dependencies": {
- "highlight.js": "^9.14.2"
- }
-}
diff --git a/docs/templates/index.html.jinja2 b/docs/templates/index.html.jinja2
deleted file mode 100644
index c7ebc85e..00000000
--- a/docs/templates/index.html.jinja2
+++ /dev/null
@@ -1,61 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Webviz configuration guide
-
-
Fundamental configuration
-
-A configuration consists of some mandatory properties (e.g. app title)
-and one or more pages. Each page has a title, and potentially some
-content. The content can be one or more items.
-
-Plugins represent predefined content, which takes one or more arguments.
-A list and description of all available different plugins is listed below.
-
-Content which is not plugins are interpreted as text paragraphs.
-
-A basic example configuration is shown below.
-
-
{{ basic_example }}
-
-
Plugin documentation
-
-{%- for package in packages.values() %}
-
-{{- package["doc"] -}}
-
-
-
-{%- for plugin in package["plugins"] %}
-
-{{ plugin["doc"] }}
-
-
-
-
-
-
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 00000000..144a4c34
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,142 @@
+{
+ "name": "webviz-config",
+ "requires": true,
+ "lockfileVersion": 1,
+ "dependencies": {
+ "clipboard": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.6.tgz",
+ "integrity": "sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg==",
+ "optional": true,
+ "requires": {
+ "good-listener": "^1.2.2",
+ "select": "^1.1.2",
+ "tiny-emitter": "^2.0.0"
+ }
+ },
+ "commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
+ },
+ "delegate": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
+ "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==",
+ "optional": true
+ },
+ "docsify": {
+ "version": "4.11.4",
+ "resolved": "https://registry.npmjs.org/docsify/-/docsify-4.11.4.tgz",
+ "integrity": "sha512-Qwt98y6ddM2Wb46gRH/zQpEAvw70AlIpzVlB9Wi2u2T2REg9O+bXMpJ27F5TaRTn2bD6SF1VyZYNUfimpihZwQ==",
+ "requires": {
+ "dompurify": "^2.0.8",
+ "marked": "^0.7.0",
+ "medium-zoom": "^1.0.5",
+ "opencollective-postinstall": "^2.0.2",
+ "prismjs": "^1.19.0",
+ "strip-indent": "^3.0.0",
+ "tinydate": "^1.0.0",
+ "tweezer.js": "^1.4.0"
+ }
+ },
+ "docsify-copy-code": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/docsify-copy-code/-/docsify-copy-code-2.1.0.tgz",
+ "integrity": "sha512-8vVJf/y4Wgd2C/GdNwctvZXczVQhWHNjihusrUcC0YP9V96KLCOERho+QAhyYR5/iRoQaLhoMaJEeuIQHNVLVw=="
+ },
+ "docsify-katex": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/docsify-katex/-/docsify-katex-1.4.3.tgz",
+ "integrity": "sha512-3wAwgETtTjZkMF749tRRqS2yJe7RcVMBcjRVNIMgUki22wetZRF2gmPu5w6rPi6JPbyPXE5M7+rUZUloRVomZg==",
+ "requires": {
+ "katex": "^0.11.1"
+ }
+ },
+ "docsify-tabs": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/docsify-tabs/-/docsify-tabs-1.4.3.tgz",
+ "integrity": "sha512-4rO+ukB3Si4BFxwHglL1llUBcMrfgayLxRj4F+2V/2zCun28SsO617dAYbB1iIzRpD0VlYrZop8+uNy4IHIs6g=="
+ },
+ "dompurify": {
+ "version": "2.0.12",
+ "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.0.12.tgz",
+ "integrity": "sha512-Fl8KseK1imyhErHypFPA8qpq9gPzlsJ/EukA6yk9o0gX23p1TzC+rh9LqNg1qvErRTc0UNMYlKxEGSfSh43NDg=="
+ },
+ "good-listener": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
+ "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
+ "optional": true,
+ "requires": {
+ "delegate": "^3.1.2"
+ }
+ },
+ "katex": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/katex/-/katex-0.11.1.tgz",
+ "integrity": "sha512-5oANDICCTX0NqYIyAiFCCwjQ7ERu3DQG2JFHLbYOf+fXaMoH8eg/zOq5WSYJsKMi/QebW+Eh3gSM+oss1H/bww==",
+ "requires": {
+ "commander": "^2.19.0"
+ }
+ },
+ "marked": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/marked/-/marked-0.7.0.tgz",
+ "integrity": "sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg=="
+ },
+ "medium-zoom": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/medium-zoom/-/medium-zoom-1.0.5.tgz",
+ "integrity": "sha512-aLGa6WlTuFKWvH88bqTrY5ztJMN+D0hd8UX6BYc4YSoPayppzETjZUcdVcksgaoQEMg4cZSmXPg846fTp2rjRQ=="
+ },
+ "min-indent": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
+ "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg=="
+ },
+ "opencollective-postinstall": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz",
+ "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q=="
+ },
+ "prismjs": {
+ "version": "1.20.0",
+ "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.20.0.tgz",
+ "integrity": "sha512-AEDjSrVNkynnw6A+B1DsFkd6AVdTnp+/WoUixFRULlCLZVRZlVQMVWio/16jv7G1FscUxQxOQhWwApgbnxr6kQ==",
+ "requires": {
+ "clipboard": "^2.0.0"
+ }
+ },
+ "select": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
+ "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=",
+ "optional": true
+ },
+ "strip-indent": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
+ "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==",
+ "requires": {
+ "min-indent": "^1.0.0"
+ }
+ },
+ "tiny-emitter": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
+ "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==",
+ "optional": true
+ },
+ "tinydate": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/tinydate/-/tinydate-1.2.0.tgz",
+ "integrity": "sha512-3GwPk8VhDFnUZ2TrgkhXJs6hcMAIIw4x/xkz+ayK6dGoQmp2nUwKzBXK0WnMsqkh6vfUhpqQicQF3rbshfyJkg=="
+ },
+ "tweezer.js": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/tweezer.js/-/tweezer.js-1.5.0.tgz",
+ "integrity": "sha512-aSiJz7rGWNAQq7hjMK9ZYDuEawXupcCWgl3woQQSoDP2Oh8O4srWb/uO1PzzHIsrPEOqrjJ2sUb9FERfzuBabQ=="
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 00000000..c2eaf06a
--- /dev/null
+++ b/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "webviz-config",
+ "description": "Documentation system for webviz-config plugins",
+ "scripts": {
+ "postinstall": "cd ./node_modules; cp ./docsify/lib/docsify.min.js ./docsify/lib/themes/vue.css ./docsify-tabs/dist/docsify-tabs.min.js ./prismjs/components/prism-bash.min.js ./prismjs/components/prism-python.min.js ./prismjs/components/prism-yaml.min.js ./docsify-copy-code/dist/docsify-copy-code.min.js ./katex/dist/katex.min.css ./docsify-katex/dist/docsify-katex.js ../INTRODUCTION.md ../webviz_config/_docs/static/; mkdir -p ../webviz_config/_docs/static/fonts; cp ./katex/dist/fonts/*.woff2 ../webviz_config/_docs/static/fonts/; cd .."
+ },
+ "author": "Equinor",
+ "license": "MIT",
+ "dependencies": {
+ "docsify": "^4.11.4",
+ "docsify-copy-code": "^2.1.0",
+ "docsify-katex": "^1.4.3",
+ "docsify-tabs": "^1.4.3",
+ "katex": "^0.11.1",
+ "prismjs": "^1.20.0"
+ }
+}
diff --git a/setup.py b/setup.py
index 555828ea..0150153e 100644
--- a/setup.py
+++ b/setup.py
@@ -23,10 +23,12 @@
packages=find_packages(exclude=["tests"]),
package_data={
"webviz_config": [
- "templates/*",
+ "_docs/static/*",
+ "_docs/static/fonts/*",
"static/*",
"static/.dockerignore",
"static/assets/*",
+ "templates/*",
"themes/default_assets/*",
]
},
@@ -42,6 +44,7 @@
"pandas>=0.24",
"pyarrow>=0.16",
"pyyaml>=5.1",
+ "typing-extensions>=3.7", # Needed on Python < 3.8
"webviz-core-components>=0.0.19",
],
tests_require=TESTS_REQUIRES,
diff --git a/webviz_config/_docs/__init__.py b/webviz_config/_docs/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/webviz_config/_docs/_build_docs.py b/webviz_config/_docs/_build_docs.py
new file mode 100644
index 00000000..5bcb774d
--- /dev/null
+++ b/webviz_config/_docs/_build_docs.py
@@ -0,0 +1,162 @@
+"""Builds automatic documentation of the installed webviz-config plugins.
+The documentation is designed to be used by the YAML configuration file end
+user. Sphinx has not been used, as the documentation from Sphinx is geared
+mostly towards Python end users. It is also a small task generating `webviz`
+documentation, and most of the Sphinx machinery is not needed.
+
+Overall workflow is:
+ * Find all installed plugins.
+ * Automatically read docstring and __init__ function signatures (both
+ argument names and which arguments have default values).
+ * Output the extracted plugin information into docsify input using jinja2.
+"""
+
+import shutil
+import inspect
+import pathlib
+from importlib import import_module
+from collections import defaultdict
+from typing import Any, Dict, Optional, Tuple
+
+import pkg_resources
+import jinja2
+from typing_extensions import TypedDict
+
+import webviz_config.plugins
+from webviz_config._config_parser import SPECIAL_ARGS
+
+
+class PluginInfo(TypedDict):
+ arg_strings: Dict[str, str]
+ argument_description: Optional[str]
+ data_input: Optional[str]
+ description: Optional[str]
+ module: str
+ name: str
+ package: str
+ package_doc: Optional[str]
+ package_version: str
+
+
+def _document_plugin(plugin: Tuple[str, Any]) -> PluginInfo:
+ """Takes in a tuple (from e.g. inspect.getmembers), and returns
+ a dictionary according to the type definition PluginInfo.
+ """
+
+ name, reference = plugin
+ docstring = reference.__doc__ if reference.__doc__ is not None else ""
+ docstring_parts = docstring.strip().split("\n---\n")
+ argspec = inspect.getfullargspec(reference.__init__)
+ module = inspect.getmodule(reference)
+ subpackage = inspect.getmodule(module).__package__ # type: ignore
+ top_package_name = subpackage.split(".")[0] # type: ignore
+
+ plugin_info: PluginInfo = {
+ "arg_strings": {arg: "" for arg in argspec.args if arg not in SPECIAL_ARGS},
+ "argument_description": docstring_parts[1]
+ if len(docstring_parts) > 1
+ else None,
+ "data_input": docstring_parts[2] if len(docstring_parts) > 2 else None,
+ "description": docstring_parts[0] if docstring != "" else None,
+ "name": name,
+ "module": module.__name__, # type: ignore
+ "package": top_package_name,
+ "package_doc": import_module(subpackage).__doc__, # type: ignore
+ "package_version": pkg_resources.get_distribution(top_package_name).version,
+ }
+
+ # Add default value and the string '# Optional' to plugin
+ # arguments with default values:
+ if argspec.defaults is not None:
+ for arg, default in dict(
+ zip(reversed(argspec.args), reversed(argspec.defaults))
+ ).items():
+ if default == "":
+ default = "''"
+ plugin_info["arg_strings"][arg] = f"{default} # Optional."
+
+ # ...and for the other arguments add '# Required':
+ for arg, string in plugin_info["arg_strings"].items():
+ if string == "":
+ plugin_info["arg_strings"][arg] = " # Required."
+
+ # Add a human readable type hint (for arguments with type annotation):
+ for arg, annotation in argspec.annotations.items():
+ if arg in plugin_info["arg_strings"]:
+ plugin_info["arg_strings"][
+ arg
+ ] += f" Type {_annotation_to_string(annotation)}."
+
+ return plugin_info
+
+
+def get_plugin_documentation() -> defaultdict:
+ """Find all installed webviz plugins, and then document them
+ by grabbing docstring and input arguments / function signature.
+ """
+
+ plugin_doc = [
+ _document_plugin(plugin)
+ for plugin in inspect.getmembers(webviz_config.plugins, inspect.isclass)
+ if not plugin[0].startswith("Example")
+ ]
+
+ # Sort the plugins by package:
+ package_ordered: defaultdict = defaultdict(lambda: {"plugins": []})
+ for sorted_plugin in sorted(plugin_doc, key=lambda x: (x["module"], x["name"])):
+ package = sorted_plugin["package"]
+ package_ordered[package]["plugins"].append(sorted_plugin)
+ package_ordered[package]["doc"] = sorted_plugin["package_doc"]
+ package_ordered[package]["version"] = sorted_plugin["package_version"]
+
+ return package_ordered
+
+
+def _annotation_to_string(annotation: Any) -> str:
+ """Takes in a type annotation (that could come from e.g. inspect.getfullargspec)
+ and transforms it into a human readable string.
+ """
+
+ def remove_fix(string: str, fix: str, prefix: bool = True) -> str:
+ if prefix and string.startswith(fix):
+ return string[len(fix) :]
+ if not prefix and string.endswith(fix):
+ return string[: -len(fix)]
+ return string
+
+ text_type = str(annotation)
+ text_type = remove_fix(text_type, "typing.")
+ text_type = remove_fix(text_type, "", prefix=False)
+ text_type = text_type.replace("pathlib.Path", "str (corresponding to a path)")
+
+ return text_type
+
+
+def build_docs(build_directory: pathlib.Path) -> None:
+
+ # From Python 3.8, copytree gets an argument dirs_exist_ok.
+ # Then the rmtree command can be removed.
+ shutil.rmtree(build_directory)
+ shutil.copytree(
+ pathlib.Path(__file__).resolve().parent / "static", build_directory,
+ )
+
+ template_environment = jinja2.Environment( # nosec
+ loader=jinja2.PackageLoader("webviz_config", "templates"),
+ undefined=jinja2.StrictUndefined,
+ autoescape=False,
+ )
+
+ plugin_documentation = get_plugin_documentation()
+
+ template = template_environment.get_template("README.md.jinja2")
+ for package_name, package_doc in plugin_documentation.items():
+ (build_directory / (package_name + ".md")).write_text(
+ template.render({"package_name": package_name, "package_doc": package_doc})
+ )
+
+ template = template_environment.get_template("sidebar.md.jinja2")
+ (build_directory / "sidebar.md").write_text(
+ template.render({"packages": plugin_documentation.keys()})
+ )
diff --git a/webviz_config/_docs/open_docs.py b/webviz_config/_docs/open_docs.py
new file mode 100644
index 00000000..2146a606
--- /dev/null
+++ b/webviz_config/_docs/open_docs.py
@@ -0,0 +1,57 @@
+import shutil
+import pathlib
+import tempfile
+import argparse
+import logging
+
+import flask
+
+import webviz_config.utils
+from ._build_docs import build_docs
+
+
+def _start_doc_app(build_directory: pathlib.Path) -> None:
+
+ app = flask.Flask(__name__, static_folder=str(build_directory), static_url_path="")
+ app.config["SEND_FILE_MAX_AGE_DEFAULT"] = 0
+
+ @app.route("/")
+ def _index() -> str:
+ return (build_directory / "index.html").read_text()
+
+ webviz_config.utils.silence_flask_startup()
+ logging.getLogger("werkzeug").setLevel(logging.WARNING)
+
+ port = webviz_config.utils.get_available_port(preferred_port=5050)
+ token = webviz_config.LocalhostToken(app, port).one_time_token
+ webviz_config.utils.LocalhostOpenBrowser(port, token)
+
+ app.run(
+ host="localhost",
+ port=port,
+ debug=False,
+ ssl_context=webviz_config.certificate.LocalhostCertificate().ssl_context,
+ )
+
+
+def open_docs(args: argparse.Namespace) -> None:
+
+ if args.portable is None:
+ build_directory = pathlib.Path(tempfile.mkdtemp())
+ else:
+ build_directory = pathlib.Path(args.portable).resolve()
+ if build_directory.exists():
+ if not args.force:
+ raise ValueError(
+ f"{build_directory} already exists. Either add --force or change output folder."
+ )
+ shutil.rmtree(build_directory)
+ build_directory.mkdir(parents=True)
+
+ try:
+ build_docs(build_directory)
+ if not args.skip_open:
+ _start_doc_app(build_directory)
+ finally:
+ if args.portable is None:
+ shutil.rmtree(build_directory)
diff --git a/webviz_config/_docs/static/README.md b/webviz_config/_docs/static/README.md
new file mode 100644
index 00000000..b26acebf
--- /dev/null
+++ b/webviz_config/_docs/static/README.md
@@ -0,0 +1,57 @@
+# Webviz introduction
+
+## Usage {docsify-ignore}
+
+Assuming you have a configuration file `your_config.yml`,
+there are two main usages of `webviz`:
+
+```bash
+webviz build your_config.yml
+```
+and
+```bash
+webviz build your_config.yml --portable ./some_output_folder
+python ./some_output_folder/webviz_app.py
+```
+
+The latter is useful when one or more plugins included in the configuration need to do
+some time-consuming data aggregation on their own, before presenting it to the user.
+The time-consuming part will then be done in the `build` step, and you can run your
+created application as many time as you want afterwards, with as little waiting
+time as possible).
+
+The `--portable` way also has the benefit of creating a :whale: Docker setup for your
+application - ready to be deployed to e.g. a cloud provider.
+
+### Fundamental configuration {docsify-ignore}
+
+A configuration consists of some mandatory properties, e.g. app title,
+and one or more pages. A page has a title and some content.
+Each page can contain as many plugins as you want.
+
+Plugins represent predefined content, which can take one or more arguments.
+Lists and descriptions of installed plugins can be found on the other subpages.
+
+Content which is not plugins is interpreted as text paragraphs.
+
+A simple example configuration:
+```yaml
+# This is a webviz configuration file example.
+# The configuration files use the YAML standard (https://en.wikipedia.org/wiki/YAML).
+
+title: Reek Webviz Demonstration
+
+pages:
+
+ - title: Front page
+ content:
+ - BannerImage:
+ image: ./example_banner.png
+ title: My banner image
+ - Webviz created from a configuration file.
+
+ - title: Markdown example
+ content:
+ - Markdown:
+ markdown_file: ./example-markdown.md
+```
diff --git a/webviz_config/_docs/static/index.html b/webviz_config/_docs/static/index.html
new file mode 100644
index 00000000..5ae05660
--- /dev/null
+++ b/webviz_config/_docs/static/index.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
Loading Webviz documentation...
+
+
+
+
+
+
+
+
+
+
+
diff --git a/webviz_config/_docs/static/webviz-doc.css b/webviz_config/_docs/static/webviz-doc.css
new file mode 100644
index 00000000..21b23b78
--- /dev/null
+++ b/webviz_config/_docs/static/webviz-doc.css
@@ -0,0 +1,26 @@
+.app-name-link > img {
+ width: 120px;
+ margin-bottom: 10px;
+}
+
+button.docsify-copy-code-button {
+ border-radius: 5px;
+}
+
+button {
+ font-family: inherit;
+}
+
+.plugin-doc {
+ background-color: white;
+ margin-top: 20px;
+ margin-bottom: 20px;
+ padding-left: 10px;
+ padding-right: 10px;
+ border: 1px solid rgb(240, 240, 240);
+ border-radius: 3px;
+}
+
+.plugin-doc:hover {
+ box-shadow: 5px 5px 10px 3px rgba(230, 230, 230);
+}
diff --git a/webviz_config/_docs/static/webviz-doc.js b/webviz_config/_docs/static/webviz-doc.js
new file mode 100644
index 00000000..24b476d0
--- /dev/null
+++ b/webviz_config/_docs/static/webviz-doc.js
@@ -0,0 +1,14 @@
+window.$docsify = {
+ logo: "./webviz-logo.svg",
+ homepage: "INTRODUCTION.md",
+ name: "Webviz",
+ loadSidebar: "sidebar.md",
+ subMaxLevel: 4,
+ copyCode: {
+ buttonText : "Copy",
+ },
+ tabs: {
+ sync: false,
+ theme: "material"
+ }
+}
diff --git a/docs/assets/webviz-logo.svg b/webviz_config/_docs/static/webviz-logo.svg
similarity index 100%
rename from docs/assets/webviz-logo.svg
rename to webviz_config/_docs/static/webviz-logo.svg
diff --git a/webviz_config/command_line.py b/webviz_config/command_line.py
index 8a5020c2..b9ddb151 100644
--- a/webviz_config/command_line.py
+++ b/webviz_config/command_line.py
@@ -1,7 +1,9 @@
import argparse
+import pathlib
from ._build_webviz import build_webviz
from .certificate._certificate_generator import create_ca
+from ._docs.open_docs import open_docs
from ._user_preferences import set_user_preferences, get_user_preference
@@ -76,6 +78,36 @@ def main() -> None:
parser_cert.set_defaults(func=create_ca)
+ # Add "documentation" parser:
+
+ parser_docs = subparsers.add_parser(
+ "docs", help="Get documentation on installed Webviz plugins",
+ )
+
+ parser_docs.add_argument(
+ "--portable",
+ type=pathlib.Path,
+ default=None,
+ metavar="OUTPUTFOLDER",
+ help="Build documentation in given folder, "
+ "which then can be deployed directly to e.g. GitHub pages.",
+ )
+
+ parser_docs.add_argument(
+ "--force",
+ action="store_true",
+ help="Overwrite existing output (this flag "
+ "only has effect if --portable is given)",
+ )
+
+ parser_docs.add_argument(
+ "--skip-open",
+ action="store_true",
+ help="Skip opening the documentation automatically in browser.",
+ )
+
+ parser_docs.set_defaults(func=open_docs)
+
# Add "preferences" parser:
parser_preferences = subparsers.add_parser(
diff --git a/webviz_config/plugins/__init__.py b/webviz_config/plugins/__init__.py
index fcc2b261..a08ccb98 100644
--- a/webviz_config/plugins/__init__.py
+++ b/webviz_config/plugins/__init__.py
@@ -1,6 +1,4 @@
-"""### _Basic plugins_
-
-These are the basic Webviz configuration plugins, distributed through
+"""These are the basic Webviz configuration plugins, distributed through
the utility itself.
"""
diff --git a/webviz_config/plugins/_banner_image.py b/webviz_config/plugins/_banner_image.py
index ecbd5da9..2daaf0d2 100644
--- a/webviz_config/plugins/_banner_image.py
+++ b/webviz_config/plugins/_banner_image.py
@@ -8,17 +8,17 @@
class BannerImage(WebvizPluginABC):
- """### Banner image
-
-Adds a full width _banner image_, with an optional overlayed title.
+ """Adds a full width banner image, with an optional overlayed title.
Useful on e.g. the front page for introducing a field or project.
-* `image`: Path to the picture you want to add. Either absolute path or
- relative to the configuration file.
-* `title`: Title which will be overlayed over the banner image.
-* `color`: Color to be used for the font.
-* `shadow`: Set to `False` if you do not want text shadow for the title.
-* `height`: Height of the banner image (in pixels).
+---
+
+* **`image`:** Path to the picture you want to add. \
+ Either absolute path or relative to the configuration file.
+* **`title`:** Title which will be overlayed over the banner image.
+* **`color`:** Color to be used for the font.
+* **`shadow`:** Set to `False` if you do not want text shadow for the title.
+* **`height`:** Height of the banner image (in pixels).
"""
TOOLBAR_BUTTONS: List[str] = []
diff --git a/webviz_config/plugins/_data_table.py b/webviz_config/plugins/_data_table.py
index 800cf3d2..eab3dc66 100644
--- a/webviz_config/plugins/_data_table.py
+++ b/webviz_config/plugins/_data_table.py
@@ -10,18 +10,18 @@
class DataTable(WebvizPluginABC):
- """### Data table
-
-Adds a table to the webviz instance, using tabular data from a provided csv file.
+ """Adds a table to the webviz instance, using tabular data from a provided csv file.
If feature is requested, the data could also come from a database.
-* `csv_file`: Path to the csv file containing the tabular data. Either absolute
+---
+
+* **`csv_file`:** Path to the csv file containing the tabular data. Either absolute \
path or relative to the configuration file.
-* `sorting`: If `True`, the table can be sorted interactively based
+* **`sorting`:** If `True`, the table can be sorted interactively based \
on data in the individual columns.
-* `filtering`: If `True`, the table can be filtered based on values in the
+* **`filtering`:** If `True`, the table can be filtered based on values in the \
individual columns.
-* `pagination`: If `True`, only a subset of the table is displayed at once.
+* **`pagination`:** If `True`, only a subset of the table is displayed at once. \
Different subsets can be viewed from 'previous/next' buttons
"""
diff --git a/webviz_config/plugins/_embed_pdf.py b/webviz_config/plugins/_embed_pdf.py
index 8d0b7259..79f8ec69 100644
--- a/webviz_config/plugins/_embed_pdf.py
+++ b/webviz_config/plugins/_embed_pdf.py
@@ -7,17 +7,16 @@
class EmbedPdf(WebvizPluginABC):
- """### Embed PDF file
+ """Embeds a given PDF file into the page.
-Embeds a given PDF file into the page.
+!> Webviz does not scan your PDF for malicious code. Make sure it comes from a trusted source.
+---
-* `pdf_file`: Path to the PDF file to include. Either absolute path or
+* **`pdf_file`:** Path to the PDF file to include. Either absolute path or \
relative to the configuration file.
-* `height`: Height of the PDF object (in percent of viewport height).
-* `width`: Width of the PDF object (in percent of available space).
+* **`height`:** Height of the PDF object (in percent of viewport height).
+* **`width`:** Width of the PDF object (in percent of available space).
-_Note_: Webviz does not scan your PDF for malicious code.
-Make sure it comes from a trusted source.
"""
def __init__(self, pdf_file: Path, height: int = 80, width: int = 100):
diff --git a/webviz_config/plugins/_markdown.py b/webviz_config/plugins/_markdown.py
index 635ca634..009cfec4 100644
--- a/webviz_config/plugins/_markdown.py
+++ b/webviz_config/plugins/_markdown.py
@@ -81,21 +81,25 @@ def handleMatch(self, m, data: str) -> tuple: # type: ignore[no-untyped-def]
class Markdown(WebvizPluginABC):
- """### Include Markdown
+ """Renders and includes the content from a Markdown file.
-_Note:_ The markdown syntax for images has been extended to support
-(optionally) providing width and/or height for individual images.
-To specify the dimensions write e.g.
-```markdown
-![width=40%,height=300px](./example_banner.png "Some caption")
-```
+---
-Renders and includes the content from a Markdown file. Images are supported,
-and should in the markdown file be given as either relative paths to
-the markdown file itself, or absolute paths.
+* **`markdown_file`:** Path to the markdown file to render and include. \
+ Either absolute path or relative to the configuration file.
+
+---
+
+Images are supported, and should in the markdown file be given as either
+relative paths to the markdown file itself, or as absolute paths.
+
+> The markdown syntax for images has been extended to support \
+ providing width and/or height for individual images (optional). \
+ To specify the dimensions write e.g.
+> ```markdown
+> ![width=40%,height=300px](./example_banner.png "Some caption")
+> ```
-* `markdown_file`: Path to the markdown file to render and include. Either
- absolute path or relative to the configuration file.
"""
ALLOWED_TAGS = [
diff --git a/webviz_config/plugins/_syntax_highlighter.py b/webviz_config/plugins/_syntax_highlighter.py
index fc67600b..ce058365 100644
--- a/webviz_config/plugins/_syntax_highlighter.py
+++ b/webviz_config/plugins/_syntax_highlighter.py
@@ -8,13 +8,13 @@
class SyntaxHighlighter(WebvizPluginABC):
- """### Syntax highlighter
+ """Adds support for syntax highlighting of code. Language is automatically detected.
-Adds support for syntax highlighting of code. Language is automatically detected.
+---
-* `filename`: Path to a file containing the code to highlight.
-* `dark_theme`: If `True`, the code is shown with a dark theme. Default is
- `False` giving a light theme.
+* **`filename`:** Path to a file containing the code to highlight.
+* **`dark_theme`:** If `True`, the code is shown with a dark theme. Default is \
+ `False`, giving a light theme.
"""
def __init__(self, filename: Path, dark_theme: bool = False):
diff --git a/webviz_config/plugins/_table_plotter.py b/webviz_config/plugins/_table_plotter.py
index 0e569937..9a591fdd 100644
--- a/webviz_config/plugins/_table_plotter.py
+++ b/webviz_config/plugins/_table_plotter.py
@@ -19,24 +19,25 @@
# pylint: disable=too-many-instance-attributes, too-many-arguments
class TablePlotter(WebvizPluginABC):
- """### TablePlotter
-
-Adds a plotter to the webviz instance, using tabular data from a provided csv file.
+ """Adds a plotter to the webviz instance, using tabular data from a provided csv file.
If feature is requested, the data could also come from a database.
-* `csv_file`: Path to the csv file containing the tabular data. Either absolute
- path or relative to the configuration file.
-* `plot_options`: A dictionary of plot options to initialize the plot with
-* `filter_cols`: Dataframe columns that can be used to filter data
-* `filter_defaults`: A dictionary with column names as keys, and a list of column values that
- should be preselected in the filter. If a columm is not defined, all values
- are preselected for the column.
-* `column_color_discrete_maps`: A dictionary with column names as keys, each key containing a new
- dictionary with the columns unique values as keys, and the color they should
- be plotted with as value. Hex values needs quotes '' to not be read as comment
- in the yaml config file.
-* `lock`: If `True`, only the plot is shown, all dropdowns for changing
- plot options are hidden.
+---
+
+* **`csv_file`:** Path to the csv file containing the tabular data. \
+ Either absolute path or relative to the configuration file.
+* **`plot_options`:** A dictionary of plot options to initialize the plot with.
+* **`filter_cols`:** Dataframe columns that can be used to filter data.
+* **`filter_defaults`:** A dictionary with column names as keys, \
+ and a list of column values that should be preselected in the filter. \
+ If a columm is not defined, all values are preselected for the column.
+* **`column_color_discrete_maps`:** A dictionary with column names as keys, \
+ each key containing a new dictionary with the columns \
+ unique values as keys, and the color they should be \
+ plotted with as value. Hex values needs quotes '' \
+ to not be read as a comment.
+* **`lock`:** If `True`, only the plot is shown, \
+ all dropdowns for changing plot options are hidden.
"""
def __init__(
diff --git a/webviz_config/templates/README.md.jinja2 b/webviz_config/templates/README.md.jinja2
new file mode 100644
index 00000000..a1604e25
--- /dev/null
+++ b/webviz_config/templates/README.md.jinja2
@@ -0,0 +1,51 @@
+# Plugin package {{ package_name }}
+
+?> :bookmark: This documentation is valid for version `{{ package_doc["version"] }}` of `{{ package_name}}`.
+
+{% if package_doc["doc"] is not none %}
+{{ package_doc["doc"] }}
+{% endif %}
+
+---
+
+{% for plugin in package_doc["plugins"] %}
+
+
+
+#### {{ plugin["name"] }}
+
+
+{% if plugin["description"] is not none %}
+
+#### ** Description **
+
+{{ plugin["description"] }}
+
+{% endif %}
+
+#### ** Arguments **
+
+{% if plugin["argument_description"] is not none %}
+{{ plugin["argument_description"] }}
+{% endif %}
+
+```yaml
+ - {{ plugin["name"] }}:
+ {%- for arg, string in plugin["arg_strings"].items() %}
+ {{ arg }}: {{ string }}
+ {%- endfor %}
+```
+
+{% if plugin["data_input"] is not none %}
+
+#### ** Data input **
+
+{{ plugin["data_input"] }}
+
+{% endif %}
+
+
+
+
+
+{% endfor %}
diff --git a/webviz_config/templates/sidebar.md.jinja2 b/webviz_config/templates/sidebar.md.jinja2
new file mode 100644
index 00000000..8c42bcde
--- /dev/null
+++ b/webviz_config/templates/sidebar.md.jinja2
@@ -0,0 +1,4 @@
+* [Introduction](/)
+{%- for package in packages %}
+* [{{package}} package]({{package}}.md)
+{%- endfor %}