Skip to content

Commit 3ba59eb

Browse files
authored
Feature: Data Sources (#1)
Multiple data sources can be defined.
1 parent 24d03f1 commit 3ba59eb

12 files changed

Lines changed: 158 additions & 54 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# mkdocs-data-plugin
22
__MkDocs Data Plugin__ is a plugin for [MkDocs](https://www.mkdocs.org/) that allows
3-
reading data from separate external markup files and use it in your Markdown pages.
3+
reading data from markup files and use it in your Markdown pages.
44

55
Currently supported formats:
66

@@ -28,7 +28,7 @@ plugins:
2828
2929
## Overview
3030
When using this plugin, you can define data in YAML or JSON files
31-
in a separate directory and reference it in your Markdown files.
31+
in a separate directory and reference them in your Markdown files.
3232
3333
```txt
3434
root/

docs/configuration/index.md

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,26 @@
22

33
This plugin provides the following configuration options.
44

5-
## Data Directory
6-
The `data_dir` option specifies the directory where data files are stored. By default, this is set to `data`.
5+
## Data Sources
6+
The `sources` option is a dictionary that defines the data sources to be used.
7+
Each key-value pair represents a source name and its corresponding directory path.
8+
9+
A source can reference directories or files.
10+
If a directory is specified, all files in the directory and its subdirectories will be loaded.
11+
12+
By default, a single data source named `data` is defined with the directory path `data`.
713

814
```yaml
915
plugins:
10-
- data:
11-
data_dir: data
16+
- sources:
17+
data: data # default
18+
foo: docs/foo.yml
1219
```
1320
1421
!!! tip
1522
It is recommended to configure the `watch` option in the `mkdocs.yml` file
16-
to automatically reload the site when data files are modified.
23+
to automatically reload the site when files in the data sources outside
24+
the `docs` directory are modified.
1725

1826
```yaml
1927
watch:

docs/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ title: Home
44
# MkDocs Data Plugin
55

66
__MkDocs Data Plugin__ is a plugin for [MkDocs](https://www.mkdocs.org/) that allows
7-
reading data from separate external markup files and use it in your Markdown pages.
7+
reading data from markup files and use it in your Markdown pages.
88

99
## Overview
1010
When using this plugin, you can define data in YAML or JSON files
11-
in a separate directory and reference it in your Markdown pages.
11+
in a separate directory and reference them in your Markdown pages.
1212

1313
```txt
1414
root/

mkdocs.yml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,17 @@ theme:
2828

2929
# Palette toggle for light mode
3030
- media: "(prefers-color-scheme: light)"
31-
primary: deep purple
32-
accent: deep purple
31+
primary: lime
32+
accent: lime
3333
scheme: default
3434
toggle:
3535
icon: material/toggle-switch
3636
name: Switch to dark mode
3737

3838
# Palette toggle for dark mode
3939
- media: "(prefers-color-scheme: dark)"
40-
primary: deep purple
41-
accent: deep purple
40+
primary: lime
41+
accent: lime
4242
scheme: slate
4343
toggle:
4444
icon: material/toggle-switch-off
@@ -66,7 +66,8 @@ plugins:
6666
use_anchor_titles: true
6767
- data
6868
- macros
69-
- social
69+
- social:
70+
enabled: !ENV [CI, false]
7071
- tags
7172
- git-revision-date-localized
7273

mkdocs_data_plugin/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
version = "0.1.0"
2-
__version__ = "0.1.0"
1+
version = "0.2.0"

mkdocs_data_plugin/plugin.py

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,60 +11,78 @@
1111

1212

1313
class DataPluginConfig(base.Config):
14-
data_dir = c.Type(str, default='data')
14+
sources = c.Type(dict, default={'data': 'data'})
1515

1616

1717
class DataPlugin(BasePlugin[DataPluginConfig]):
1818
def __init__(self):
19-
self.data = {}
19+
self.sources = {}
2020
self.processors = {'.yml': yaml.safe_load, '.yaml': yaml.safe_load, '.json': json.load}
2121

22-
def set_data(self, keys, value):
22+
def load_sources(self):
2323
"""
24-
Set a value in the data attribute.
24+
Load all sources from the config file and load the data from the files.
2525
"""
26-
data = self.data
27-
for key in keys[:-1]:
28-
data = data.setdefault(key, {})
29-
data[keys[-1]] = value
26+
for source, path in self.config['sources'].items():
27+
if not os.path.exists(path):
28+
log.warning(f"Mapping path '{path}' not found. Skipping.")
29+
elif os.path.isdir(path):
30+
self.load_folder(source, path)
31+
else:
32+
value = self.load_file(path)
33+
self.update_data(source, [], value)
3034

31-
def on_config(self, config: MkDocsConfig):
32-
self.load_data(self.config.data_dir)
33-
34-
macros_plugin = config.plugins.get('macros')
35-
if macros_plugin:
36-
macros_plugin.register_variables({'data': self.data})
35+
def update_data(self, source: str, keys: list, value: any):
36+
"""
37+
Update the sources data with the given value.
38+
"""
39+
if len(keys) == 0:
40+
self.sources[source] = value
3741
else:
38-
log.warning(
39-
"The macros plugin is not installed. The `data` variable won't be available in pages."
40-
)
42+
data = self.sources.setdefault(source, {})
43+
for key in keys[:-1]:
44+
data = data.setdefault(key, {})
45+
data[keys[-1]] = value
4146

42-
def load_data(self, path: str):
47+
def load_folder(self, source: str, path: str):
4348
"""
4449
Iterate over all files in the data directory
4550
and load them into the data attribute.
4651
"""
4752
for root, _, files in os.walk(path):
4853

4954
keys = []
50-
if root != self.config.data_dir:
51-
directory = os.path.relpath(root, self.config.data_dir)
55+
if root != path:
56+
directory = os.path.relpath(root, path)
5257
keys = directory.split(os.sep)
5358

5459
for file in files:
5560
value = self.load_file(os.path.join(root, file))
5661

5762
filename, _ = os.path.splitext(file)
58-
self.set_data(keys + [filename], value)
63+
self.update_data(source, keys + [filename], value)
5964

6065
def load_file(self, path: str):
6166
"""
62-
Load a file and return its content.
67+
Loads a file and processes it with the appropriate processor.
6368
"""
6469
_, extension = os.path.splitext(path)
6570
with open(path, 'r') as file:
6671
return self.processors[extension](file)
6772

73+
def on_config(self, config: MkDocsConfig):
74+
self.load_sources()
75+
76+
macros_plugin = config.plugins.get('macros')
77+
if macros_plugin:
78+
for source, data in self.sources.items():
79+
macros_plugin.register_variables({source: data})
80+
else:
81+
log.warning(
82+
"The macros plugin is not installed. The `data` variable won't be available in pages."
83+
)
84+
6885
def on_page_context(self, context, page, config, nav):
69-
context['data'] = self.data
86+
for source, data in self.sources.items():
87+
context[source] = data
7088
return context

tests/docs/fruits.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
- Apple
2+
- Banana
3+
- Strawberry
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
title: "Test Data Template"
2+
title: "Test Directory Source"
33
---
44

55
- data.a: `{{ data.a }}`

tests/docs/test_file_source.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
title: "Test File Source"
3+
---
4+
5+
{% for fruit in fruits %}
6+
- `{{ fruit }}`
7+
{% endfor %}

tests/test_config.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
def test_config_default_values():
77
plugin = DataPlugin()
88
plugin.load_config({})
9-
assert plugin.config.data_dir == 'data'
9+
assert plugin.config.sources == {'data': 'data'}
1010

1111

12-
def test_config_data_dir():
12+
def test_config_sources():
1313
plugin = DataPlugin()
14-
plugin.load_config({'data_dir': 'other_data'})
15-
assert plugin.config.data_dir == 'other_data'
14+
plugin.load_config({'sources': {'data': 'other_data'}})
15+
assert plugin.config.sources == {'data': 'other_data'}

0 commit comments

Comments
 (0)