Skip to content

Commit 4b16464

Browse files
authored
MRG: Merge pull request #735 from octue/move-twined-library-into-octue-sdk
Move `twined` package into `octue`
2 parents 5df29a8 + b511967 commit 4b16464

File tree

82 files changed

+69551
-229
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+69551
-229
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from sphinx.errors import ExtensionError
2+
3+
4+
def add_ga_javascript(app, pagename, templatename, context, doctree):
5+
if app.config.googleanalytics_enabled:
6+
id = app.config.googleanalytics_id
7+
metatags = context.get("metatags", "")
8+
metatags += "<!-- Global site tag (gtag.js) - Google Analytics -->\n"
9+
metatags += f'<script async src="https://www.googletagmanager.com/gtag/js?id={id}"></script>\n'
10+
metatags += "<script>\n"
11+
metatags += " window.dataLayer = window.dataLayer || [];\n"
12+
metatags += " function gtag(){dataLayer.push(arguments);}\n"
13+
metatags += " gtag('js', new Date());\n"
14+
metatags += f" gtag('config', '{id}');\n"
15+
metatags += "</script>\n"
16+
context["metatags"] = metatags
17+
18+
19+
def check_config(app):
20+
if not app.config.googleanalytics_id:
21+
raise ExtensionError("'googleanalytics_id' config value must be set for ga statistics to function properly.")
22+
23+
24+
def setup(app):
25+
app.add_config_value("googleanalytics_id", "", "html")
26+
app.add_config_value("googleanalytics_enabled", True, "html")
27+
app.connect("html-page-context", add_ga_javascript)
28+
app.connect("builder-inited", check_config)
29+
return {"version": "0.1"}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
```
2+
extensions = [
3+
...
4+
'sphinx_accordion.accordion'
5+
...
6+
]
7+
```
8+
9+
```
10+
.. accordion::
11+
12+
.. accordion-row:: The Title
13+
14+
The Contents
15+
16+
.. accordion-row:: The Second Title
17+
18+
The Contents 2
19+
```

docs/source/_ext/sphinx_accordion/__init__.py

Whitespace-only changes.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
.sphinx-accordion.accordion {
2+
margin-bottom: 1.75em;
3+
}
4+
5+
.sphinx-accordion.title p {
6+
display: inline-block;
7+
margin-top: 8px;
8+
margin-right: 0px;
9+
margin-bottom: 8px;
10+
margin-left: 0px;
11+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// if (!String.prototype.startsWith) {
2+
// Object.defineProperty(String.prototype, 'startsWith', {
3+
// value: function(search, pos) {
4+
// pos = !pos || pos < 0 ? 0 : +pos;
5+
// return this.substring(pos, pos + search.length) === search;
6+
// }
7+
// });
8+
// }
9+
10+
$(document).ready(function () {
11+
console.log("FFS");
12+
});
13+
14+
$(function () {
15+
console.log("SOMETHING HAPPENS MAYBE");
16+
17+
// We store the data-row values as sphinx-data-<data-row value>
18+
// Add data-row attribute with the extracted value
19+
$(".sphinx-accordion.title").each(function () {
20+
const this1 = $(this);
21+
const prefix = "sphinx-accordion-title-";
22+
const classes = this1.attr("class").split(/\s+/);
23+
$.each(classes, function (idx, clazz) {
24+
if (clazz.startsWith(prefix)) {
25+
this1.attr("data-row", clazz.substring(prefix.length));
26+
}
27+
});
28+
29+
const data_row = this1.attr("data-row");
30+
31+
this1.on("click", function () {
32+
// Find offset in view
33+
const offset = this1.offset().top - $(window).scrollTop();
34+
35+
// Toggle active class on this subsequent sibling
36+
if (this1.hasClass("active")) {
37+
this1.removeClass("active");
38+
this1.next().removeClass("active");
39+
} else {
40+
this1.addClass("active");
41+
this1.next().addClass("active");
42+
}
43+
44+
// Keep tab with the original view offset
45+
$(window).scrollTop(this1.offset().top - offset);
46+
});
47+
});
48+
});
Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
"""Accordion dropdown for Sphinx, with HTML builder"""
2+
3+
import json
4+
import os
5+
import posixpath
6+
7+
from docutils import nodes
8+
from docutils.parsers.rst import Directive
9+
from pkg_resources import resource_filename
10+
from pygments.lexers import get_all_lexers
11+
from sphinx.util import logging
12+
from sphinx.util.osutil import copyfile
13+
14+
FILES = [
15+
"semantic-ui-2.4.2/accordion.css",
16+
"semantic-ui-2.4.2/accordion.js",
17+
"accordion.css",
18+
"accordion.js",
19+
]
20+
21+
22+
LEXER_MAP = {}
23+
for lexer in get_all_lexers():
24+
for short_name in lexer[1]:
25+
LEXER_MAP[short_name] = lexer[0]
26+
27+
28+
def get_compatible_builders(app):
29+
builders = [
30+
"html",
31+
"singlehtml",
32+
"dirhtml",
33+
"readthedocs",
34+
"readthedocsdirhtml",
35+
"readthedocssinglehtml",
36+
"readthedocssinglehtmllocalmedia",
37+
"spelling",
38+
]
39+
builders.extend(app.config["sphinx_tabs_valid_builders"])
40+
return builders
41+
42+
43+
class AccordionDirective(Directive):
44+
"""Top-level accordion directive"""
45+
46+
has_content = True
47+
48+
def run(self):
49+
"""Parse an accordion directive"""
50+
self.assert_has_content()
51+
env = self.state.document.settings.env
52+
53+
node = nodes.container()
54+
node["classes"] = ["sphinx-accordion", "ui", "styled", "fluid", "accordion"]
55+
56+
if "next_accordion_id" not in env.temp_data:
57+
env.temp_data["next_accordion_id"] = 0
58+
if "accordion_stack" not in env.temp_data:
59+
env.temp_data["accordion_stack"] = []
60+
61+
accordion_id = env.temp_data["next_accordion_id"]
62+
accordion_key = "accordion_%d" % accordion_id
63+
env.temp_data["next_accordion_id"] += 1
64+
env.temp_data["accordion_stack"].append(accordion_id)
65+
66+
env.temp_data[accordion_key] = {}
67+
env.temp_data[accordion_key]["row_ids"] = []
68+
env.temp_data[accordion_key]["row_titles"] = []
69+
env.temp_data[accordion_key]["is_first_row"] = True
70+
71+
self.state.nested_parse(self.content, self.content_offset, node)
72+
73+
if env.app.builder.name in get_compatible_builders(env.app):
74+
title_nodes = []
75+
row_ids = env.temp_data[accordion_key]["row_ids"]
76+
row_titles = env.temp_data[accordion_key]["row_titles"]
77+
for idx, [data_row, row_name] in enumerate(row_titles):
78+
title_node = nodes.container()
79+
title_node.tagname = "div"
80+
title_node["classes"] = ["sphinx-accordion", "title"]
81+
title_node["classes"].append(f"sphinx-accordion-title-{accordion_id}-{row_ids[idx]}")
82+
title_node += row_name.children
83+
icon_node = nodes.inline()
84+
icon_node.tagname = "i"
85+
icon_node["classes"] = ["dropdown", "icon"]
86+
# Access the first child, we don't want the container that somehow gets generated
87+
title_node.children.insert(0, icon_node)
88+
title_nodes.append(title_node)
89+
90+
node.children = [child for pair in zip(title_nodes, node.children) for child in pair]
91+
92+
env.temp_data["accordion_stack"].pop()
93+
return [node]
94+
95+
96+
class AccordionRowDirective(Directive):
97+
"""AccordionRow directive, for adding a row to an accordion"""
98+
99+
has_content = True
100+
101+
def run(self):
102+
"""Parse a row directive"""
103+
self.assert_has_content()
104+
env = self.state.document.settings.env
105+
106+
accordion_id = env.temp_data["accordion_stack"][-1]
107+
accordion_key = "accordion_%d" % accordion_id
108+
109+
args = self.content[0].strip()
110+
if args.startswith("{"):
111+
try:
112+
args = json.loads(args)
113+
self.content.trim_start(1)
114+
except ValueError:
115+
args = {}
116+
else:
117+
args = {}
118+
119+
row_name = nodes.container()
120+
self.state.nested_parse(self.content[:1], self.content_offset, row_name)
121+
args["row_name"] = row_name
122+
123+
include_accordion_id_in_data_row = False
124+
if "row_id" not in args:
125+
args["row_id"] = env.new_serialno(accordion_key)
126+
include_accordion_id_in_data_row = True
127+
i = 1
128+
while args["row_id"] in env.temp_data[accordion_key]["row_ids"]:
129+
args["row_id"] = "%s-%d" % (args["row_id"], i)
130+
i += 1
131+
env.temp_data[accordion_key]["row_ids"].append(args["row_id"])
132+
133+
data_row = str(args["row_id"])
134+
if include_accordion_id_in_data_row:
135+
data_row = "%d-%s" % (accordion_id, data_row)
136+
data_row = "sphinx-accordion-content-{}".format(data_row)
137+
138+
env.temp_data[accordion_key]["row_titles"].append((data_row, args["row_name"]))
139+
140+
text = "\n".join(self.content)
141+
node = nodes.container(text)
142+
classes = "sphinx-accordion content"
143+
node["classes"] = classes.split(" ")
144+
node["classes"].extend(args.get("classes", []))
145+
node["classes"].append(data_row)
146+
147+
self.state.nested_parse(self.content[2:], self.content_offset, node)
148+
149+
if env.app.builder.name not in get_compatible_builders(env.app):
150+
outer_node = nodes.container()
151+
row = nodes.container()
152+
row.tagname = "a"
153+
row["classes"] = ["item"]
154+
row += row_name
155+
outer_node.append(row)
156+
outer_node.append(node)
157+
return [outer_node]
158+
159+
return [node]
160+
161+
162+
class _FindAccordionDirectiveVisitor(nodes.NodeVisitor):
163+
"""Visitor pattern than looks for a sphinx accordion directive in a document"""
164+
165+
def __init__(self, document):
166+
nodes.NodeVisitor.__init__(self, document)
167+
self._found = False
168+
169+
def unknown_visit(self, node):
170+
if (
171+
not self._found
172+
and isinstance(node, nodes.container)
173+
and "classes" in node
174+
and isinstance(node["classes"], list)
175+
):
176+
self._found = "sphinx-accordion" in node["classes"]
177+
178+
@property
179+
def found_accordion_directive(self):
180+
"""Return whether a sphinx accordion directive was found"""
181+
return self._found
182+
183+
184+
def update_context(app, pagename, templatename, context, doctree):
185+
"""Remove sphinx-accordion CSS and JS asset files if not used in a page"""
186+
if doctree is None:
187+
return
188+
visitor = _FindAccordionDirectiveVisitor(doctree)
189+
doctree.walk(visitor)
190+
if not visitor.found_accordion_directive:
191+
paths = [posixpath.join("_static", "sphinx_accordion/" + f) for f in FILES]
192+
if "css_files" in context:
193+
context["css_files"] = context["css_files"][:]
194+
for path in paths:
195+
if path.endswith(".css") and path in context["css_files"]:
196+
context["css_files"].remove(path)
197+
if "script_files" in context:
198+
context["script_files"] = context["script_files"][:]
199+
for path in paths:
200+
if path.endswith(".js") and path in context["script_files"]:
201+
context["script_files"].remove(path)
202+
203+
204+
def copy_assets(app, exception):
205+
"""Copy asset files to the output"""
206+
if "getLogger" in dir(logging):
207+
log = logging.getLogger(__name__).info
208+
warn = logging.getLogger(__name__).warning
209+
else:
210+
log = app.info
211+
warn = app.warning
212+
builders = get_compatible_builders(app)
213+
if exception:
214+
return
215+
if app.builder.name not in builders:
216+
if not app.config["sphinx_accordion_nowarn"]:
217+
warn("Not copying accordion assets! Not compatible with %s builder" % app.builder.name)
218+
return
219+
220+
log("Copying accordion assets")
221+
222+
installdir = os.path.join(app.builder.outdir, "_static", "sphinx_accordion")
223+
224+
for path in FILES:
225+
source = resource_filename("sphinx_accordion", path)
226+
dest = os.path.join(installdir, path)
227+
destdir = os.path.dirname(dest)
228+
if not os.path.exists(destdir):
229+
os.makedirs(destdir)
230+
231+
copyfile(source, dest)
232+
233+
234+
def setup(app):
235+
"""Set up the plugin"""
236+
app.add_config_value("sphinx_accordion_nowarn", False, "")
237+
app.add_config_value("sphinx_accordion_valid_builders", [], "")
238+
app.add_directive("accordion", AccordionDirective)
239+
app.add_directive("accordion-row", AccordionRowDirective)
240+
241+
for path in ["sphinx_accordion/" + f for f in FILES]:
242+
if path.endswith(".css"):
243+
if "add_css_file" in dir(app):
244+
app.add_css_file(path)
245+
else:
246+
app.add_stylesheet(path)
247+
if path.endswith(".js"):
248+
if "add_script_file" in dir(app):
249+
app.add_script_file(path)
250+
else:
251+
app.add_js_file(path)
252+
253+
app.connect("html-page-context", update_context)
254+
app.connect("build-finished", copy_assets)
255+
256+
return {
257+
"parallel_read_safe": True,
258+
"parallel_write_safe": True,
259+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2+
3+

0 commit comments

Comments
 (0)