mkdocs 2.0.dev3__py3-none-any.whl → 2.0.dev5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
mkdocs/__version__.py CHANGED
@@ -1,2 +1,2 @@
1
1
  __title__ = "mkdocs"
2
- __version__ = "2.0.dev3"
2
+ __version__ = "2.0.dev5"
@@ -34,15 +34,13 @@ class URLProcessor(markdown.treeprocessors.Treeprocessor):
34
34
  path_from = page.path
35
35
  path_to = os.path.normpath(path_from.parent.joinpath(url.path))
36
36
 
37
- target = site.lookup.get(path_to)
37
+ target = site.lookup_by_path(path_to)
38
38
  if target is None:
39
39
  continue # Broken link!
40
40
 
41
41
  url_from = page.url
42
42
  url_to = target.url
43
- rewrite = posixpath.relpath(url_to, url_from)
44
- if url_to.endswith('/') and rewrite != '.':
45
- rewrite += '/'
43
+ rewrite = mkdocs.link_to(url_from, url_to)
46
44
  if url.query:
47
45
  rewrite += f'?{url.query}'
48
46
  if url.fragment:
mkdocs/mkdocs.py CHANGED
@@ -20,7 +20,7 @@ RESET = '\033[0m'
20
20
  # The build context is used to ensure the current page and the site index
21
21
  # are available to the RelativeURLs markdown extension.
22
22
  _current_page = contextvars.ContextVar('current_page')
23
- _site_index = contextvars.ContextVar('site_index')
23
+ _site = contextvars.ContextVar('site')
24
24
 
25
25
 
26
26
  def get_current_page():
@@ -31,12 +31,24 @@ def get_current_page():
31
31
 
32
32
 
33
33
  def get_site():
34
- ctx = _site_index.get()
34
+ ctx = _site.get()
35
35
  if ctx is None:
36
36
  raise RuntimeError("No current context")
37
37
  return ctx
38
38
 
39
39
 
40
+ def link_to(path_from, path_to):
41
+ if path_from == path_to:
42
+ return '.'
43
+ p0 = path_from.split('/')
44
+ p1 = path_to.split('/')
45
+ for idx, pair in enumerate(zip(p0, p1)):
46
+ if pair[0] != pair[1]:
47
+ break
48
+ p = ['..' for i in p0[idx+1:]] + p1[idx:]
49
+ return '/'.join(p)
50
+
51
+
40
52
  class Page:
41
53
  def __init__(self, path):
42
54
  self.path = path
@@ -64,13 +76,19 @@ class Site:
64
76
  self._pages = pages
65
77
  self._statics = statics
66
78
 
67
- self.lookup = {
79
+ self._paths = {
68
80
  str(resource.path): resource for resource in pages + statics
69
81
  }
70
- self.lookup_by_url = {
82
+ self._urls = {
71
83
  str(resource.url): resource for resource in pages + statics
72
84
  }
73
85
 
86
+ def lookup_by_path(self, path) -> Page | Static | None:
87
+ return self._paths.get(path)
88
+
89
+ def lookup_by_url(self, url) -> Page | Static | None:
90
+ return self._urls.get(url)
91
+
74
92
  @property
75
93
  def pages(self) -> list[Page]:
76
94
  return list(self._pages)
@@ -93,6 +111,26 @@ class TableOfContents:
93
111
  return bool(self._items)
94
112
 
95
113
 
114
+ class NavItem:
115
+ def __init__(self, title: str, page: Page):
116
+ self.title = title
117
+ self.page = page
118
+
119
+
120
+ class Navigation:
121
+ def __init__(self, nav_items):
122
+ self._items = nav_items
123
+
124
+ def __iter__(self):
125
+ return iter(self._items)
126
+
127
+ @property
128
+ def html(self):
129
+ page = get_current_page()
130
+ t = jinja2.Template("""<ul>{% for item in nav %}<li><a href="{{ item.page.url }}" {% if item.page == page %}class="active"{% endif %}>{{ item.title }}</a></li>{% endfor %}</ul>""")
131
+ return t.render({"nav": self, "page": page})
132
+
133
+
96
134
  class PageContext:
97
135
  def __init__(self, page, text, html, toc):
98
136
  self.path = page.path
@@ -110,7 +148,8 @@ class PageContext:
110
148
 
111
149
  class MkDocs:
112
150
  def __init__(self, input_dir):
113
- self.site_index = self.load_site(input_dir)
151
+ self.site = self.load_site(input_dir)
152
+ self.nav = self.load_nav({}, self.site)
114
153
  self.env = self.init_env(input_dir)
115
154
  self.md = self.init_md()
116
155
  self.base = self.env.get_template('base.html')
@@ -140,12 +179,34 @@ class MkDocs:
140
179
  statics = sorted(statics, key=lambda x: x.url)
141
180
  return Site(pages, statics)
142
181
 
182
+ def load_nav(self, config, site):
183
+ if not config:
184
+ config = {"nav": [
185
+ {"title": page.path.stem, "path": str(page.path)}
186
+ for page in site.pages
187
+ ]}
188
+
189
+ nav_config = config.get('nav', [])
190
+ nav_config = nav_config if isinstance(nav_config, list) else []
191
+ nav_items = []
192
+ for item in nav_config:
193
+ if not isinstance(item, dict):
194
+ continue
195
+ path = item.get('path', '')
196
+ title = item.get('title', '')
197
+ if not path:
198
+ continue
199
+ if path:
200
+ page = site.lookup_by_path(path)
201
+ nav_item = NavItem(title, page)
202
+ nav_items.append(nav_item)
203
+ return Navigation(nav_items)
204
+
143
205
  def init_env(self, input_dir) -> jinja2.Environment:
144
206
  @jinja2.pass_context
145
207
  def url(ctx, url_to):
146
208
  url_from = ctx['page'].url
147
- url_rel = posixpath.relpath(url_to, url_from) # This isn't correct
148
- return url_rel
209
+ return link_to(url_from, url_to)
149
210
 
150
211
  dir = pathlib.Path(input_dir)
151
212
  loader = jinja2.ChoiceLoader([
@@ -178,19 +239,21 @@ class MkDocs:
178
239
  @contextlib.contextmanager
179
240
  def set_context(self, current_page):
180
241
  token_page = _current_page.set(current_page)
181
- token_site = _site_index.set(self.site_index)
242
+ token_site = _site.set(self.site)
182
243
  try:
183
244
  yield
184
245
  finally:
185
246
  _current_page.reset(token_page)
186
- _site_index.reset(token_site)
247
+ _site.reset(token_site)
248
+
249
+ # Commands...
187
250
 
188
251
  def build(self, input, output):
189
252
  input_dir = pathlib.Path(input)
190
253
  output_dir = pathlib.Path(output)
191
254
 
192
- print(DARK_GRAY + "Collected %d resources" % len(self.site_index) + RESET)
193
- for page in self.site_index.pages:
255
+ print(DARK_GRAY + "Collected %d resources" % len(self.site) + RESET)
256
+ for page in self.site.pages:
194
257
  print(GREEN + " + " + RESET + BOLD + str(page.path) + RESET + DARK_GRAY + " [markdown]" + RESET)
195
258
  input_path = input_dir.joinpath(page.path)
196
259
  output_path = output_dir.joinpath(page.build_path)
@@ -200,12 +263,12 @@ class MkDocs:
200
263
  html = self.md.reset().convert(text)
201
264
  toc = TableOfContents(self.md)
202
265
  page_ctx = PageContext(page=page, text=text, html=html, toc=toc)
203
- output = self.base.render(page=page_ctx)
266
+ output = self.base.render(page=page_ctx, nav=self.nav)
204
267
 
205
268
  output_path.parent.mkdir(parents=True, exist_ok=True)
206
269
  output_path.write_text(output)
207
270
 
208
- for static in self.site_index.statics:
271
+ for static in self.site.statics:
209
272
  print(GREEN + " + " + RESET + BOLD + str(static.path) + RESET + DARK_GRAY + " [static]" + RESET)
210
273
  input_path = input_dir.joinpath(static.path)
211
274
  output_path = output_dir.joinpath(static.path)
@@ -216,15 +279,15 @@ class MkDocs:
216
279
  def serve(self, input):
217
280
  input_dir = pathlib.Path(input)
218
281
 
219
- print(DARK_GRAY + "Serving %d resources" % len(self.site_index) + RESET)
220
- for page in self.site_index.pages:
282
+ print(DARK_GRAY + "Serving %d resources" % len(self.site) + RESET)
283
+ for page in self.site.pages:
221
284
  print(GREEN + " + " + RESET + BOLD + str(page.url) + RESET + DARK_GRAY + " [markdown]" + RESET)
222
- for static in self.site_index.statics:
285
+ for static in self.site.statics:
223
286
  print(GREEN + " + " + RESET + BOLD + str(static.url) + RESET + DARK_GRAY + " [static]" + RESET)
224
287
  print()
225
288
 
226
289
  def app(request):
227
- resource = self.site_index.lookup_by_url.get(request.url.path)
290
+ resource = self.site.lookup_by_url(request.url.path)
228
291
 
229
292
  if isinstance(resource, Page):
230
293
  input_path = input_dir.joinpath(resource.path)
@@ -233,7 +296,7 @@ class MkDocs:
233
296
  html = self.md.reset().convert(text)
234
297
  toc = TableOfContents(self.md)
235
298
  page_ctx = PageContext(page=resource, text=text, html=html, toc=toc)
236
- output = self.base.render(page=page_ctx)
299
+ output = self.base.render(page=page_ctx, nav=self.nav)
237
300
  return httpx.Response(200, content=httpx.HTML(output))
238
301
  elif isinstance(resource, Static):
239
302
  input_path = input_dir.joinpath(resource.path)
@@ -244,6 +307,8 @@ class MkDocs:
244
307
  server.serve()
245
308
 
246
309
 
310
+ # Command line client...
311
+
247
312
  @click.group()
248
313
  def cli():
249
314
  if pathlib.Path('mkdocs.yml').exists():
mkdocs/theme/base.html CHANGED
@@ -43,19 +43,33 @@ main {
43
43
 
44
44
  @media (max-width: 1000px) {
45
45
  main {
46
+ margin-left: 20%;
46
47
  width: 75%;
47
48
  }
48
49
 
49
50
  nav.toc {
50
51
  display: none;
51
52
  }
53
+
54
+ nav.site {
55
+ width: 25%;
56
+ }
52
57
  }
53
58
 
54
- @media (max-width: 600px) {
59
+ @media (max-width: 750px) {
55
60
  main {
61
+ margin-left: 0;
56
62
  width: 100%;
57
63
  padding: 1rem 1.5rem;
58
64
  }
65
+
66
+ nav.toc {
67
+ display: none;
68
+ }
69
+
70
+ nav.site {
71
+ display: none;
72
+ }
59
73
  }
60
74
 
61
75
  /* Typography & spacing */
@@ -168,6 +182,14 @@ a.toclink:hover::after {
168
182
 
169
183
  /* Table of contents styling */
170
184
 
185
+ nav.site {
186
+ position: fixed;
187
+ width : 20%;
188
+ padding: 2rem;
189
+ height: 100%;
190
+ overflow-y: scroll;
191
+ }
192
+
171
193
  nav.toc {
172
194
  position: fixed;
173
195
  margin-left: 80%;
@@ -179,6 +201,35 @@ nav.toc {
179
201
 
180
202
  /* Navigation styling */
181
203
 
204
+ nav.site ul {
205
+ padding: 0;
206
+ margin: 0;
207
+ }
208
+
209
+ nav.site li {
210
+ padding: 0;
211
+ margin: 0.5rem 0;
212
+ display: block;
213
+ }
214
+
215
+ nav.site li a.active {
216
+ color: var(--link-color);
217
+ }
218
+
219
+ nav.site li a:hover {
220
+ color: var(--link-color);
221
+ text-decoration: none;
222
+ }
223
+
224
+ nav.site li a {
225
+ color: var(--muted-fg-color);
226
+ }
227
+
228
+ nav.site li a:hover {
229
+ color: var(--fg-color);
230
+ text-decoration: none;
231
+ }
232
+
182
233
  nav.toc ul {
183
234
  padding: 0;
184
235
  margin: 0;
@@ -210,6 +261,11 @@ nav.toc li a:hover {
210
261
  </style>
211
262
  </head>
212
263
  <body>
264
+ {% if nav %}
265
+ <nav class="site">
266
+ {% include "navigation.html" %}
267
+ </nav>
268
+ {% endif %}
213
269
  {% if page.toc %}
214
270
  <nav class="toc">
215
271
  {{ page.toc.html }}
@@ -0,0 +1,3 @@
1
+ <ul>
2
+ {% for item in nav %}<li><a href="{{ item.page.url | url }}"{% if item.page.url == page.url %} class="active"{% endif %}>{{ item.title }}</a></li>{% endfor %}
3
+ </ul>
@@ -0,0 +1,74 @@
1
+ Metadata-Version: 2.5
2
+ Name: mkdocs
3
+ Version: 2.0.dev5
4
+ Summary: HTTP, for Python.
5
+ Author-email: Kim Christie <noreply@lovelydinosaur.com>
6
+ Classifier: Development Status :: 4 - Beta
7
+ Classifier: Environment :: Web Environment
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Topic :: Internet :: WWW/HTTP
16
+ Requires-Python: >=3.10
17
+ Requires-Dist: click
18
+ Requires-Dist: httpx>=1.0.dev6
19
+ Requires-Dist: jinja2
20
+ Requires-Dist: markdown
21
+ Description-Content-Type: text/markdown
22
+
23
+ # MkDocs
24
+
25
+ MkDocs is a smart, simple, website design tool.
26
+
27
+ ## Installation
28
+
29
+ To install MkDocs, run the following command from the command line:
30
+
31
+ ```shell
32
+ pip install mkdocs --pre
33
+ ```
34
+
35
+ This will install the version 2.0 pre-release.
36
+
37
+ ## Getting started
38
+
39
+ 1. Create a `docs/README.md` page.
40
+ 2. Run `mkdocs serve` to view your documentation in a browser.
41
+ 3. Run `mkdocs build` to build a static website ready to host.
42
+
43
+ ## Writing your docs
44
+
45
+ 1. Create additional markdown pages.
46
+ 2. Use relative interlinking between pages.
47
+ 3. Include images and use relative interlinking from pages.
48
+
49
+ *MkDocs supports [GitHub Flavored Markdown](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax) for page authoring.*
50
+
51
+ ## Styling your docs
52
+
53
+ 1. Create a `templates/base.html` to customise the styling.
54
+ 2. Include css and javascript to serve static files.
55
+
56
+ *MkDocs uses [Jinja templating](https://jinja.palletsprojects.com/en/stable/templates/) for HTML rendering.*
57
+
58
+ A starting point can be as simple as...
59
+
60
+ ```html
61
+ <html>
62
+ <head>
63
+ <meta charset="utf-8">
64
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
65
+ <title>{{ page.toc.title }}</title>
66
+ <link rel="stylesheet" href="{{ '/css/default.css' | url }}">
67
+ </head>
68
+ <body>
69
+ <main>
70
+ {{ page.html }}
71
+ </main>
72
+ </body>
73
+ </html>
74
+ ```
@@ -0,0 +1,13 @@
1
+ mkdocs/__init__.py,sha256=NwNA-Nxju0I4e1-Msqo_ewJLRcjJjEMiVs2bbfzoMCg,283
2
+ mkdocs/__version__.py,sha256=wk6npcQOpkv95xsvTaNoOpDNXZLjJ10qrE-tday-4e4,46
3
+ mkdocs/mkdocs.py,sha256=Lv_LVrZCLaznNfP9R_0CKS3ALVxuBok9Q_xWTux3PXM,10484
4
+ mkdocs/extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ mkdocs/extensions/relative_urls.py,sha256=AS-d1CraHrAFT83RZlpJE8T4cL-CH8h5KC-pwNdd7G4,1848
6
+ mkdocs/extensions/short_codes.py,sha256=I2SwGMcG9OT_vpkJwPI8cHBTkwQAjSPZmoQKfctsHn4,950
7
+ mkdocs/extensions/strike_thru.py,sha256=GrCbfMrHz_2Vlh3E572EQYOSDzEGym34pkHElzF2HZY,577
8
+ mkdocs/theme/base.html,sha256=mioyexMGSzSLbjxINKd-V1Go5UqyhALVfqtkQ2n8UrQ,4286
9
+ mkdocs/theme/navigation.html,sha256=BI5tAPZva9MrAVcuUOBlTJi_Xn1XyBq_2-y69Bdkabw,174
10
+ mkdocs-2.0.dev5.dist-info/METADATA,sha256=RQhYo24CafCop9w3eojiL30avsbipnF9m0Ly9SVAQS8,2205
11
+ mkdocs-2.0.dev5.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
12
+ mkdocs-2.0.dev5.dist-info/entry_points.txt,sha256=5PqBrzYJLZ9-yQ0djvENWOQ-0x6Xj30JYNSzM_m70ZU,38
13
+ mkdocs-2.0.dev5.dist-info/RECORD,,
@@ -1,20 +0,0 @@
1
- Metadata-Version: 2.5
2
- Name: mkdocs
3
- Version: 2.0.dev3
4
- Summary: HTTP, for Python.
5
- Author-email: Kim Christie <noreply@lovelydinosaur.com>
6
- Classifier: Development Status :: 4 - Beta
7
- Classifier: Environment :: Web Environment
8
- Classifier: Intended Audience :: Developers
9
- Classifier: Operating System :: OS Independent
10
- Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: 3.10
12
- Classifier: Programming Language :: Python :: 3.11
13
- Classifier: Programming Language :: Python :: 3.12
14
- Classifier: Programming Language :: Python :: 3.13
15
- Classifier: Topic :: Internet :: WWW/HTTP
16
- Requires-Python: >=3.10
17
- Requires-Dist: click
18
- Requires-Dist: httpx>=1.0.dev5
19
- Requires-Dist: jinja2
20
- Requires-Dist: markdown
@@ -1,12 +0,0 @@
1
- mkdocs/__init__.py,sha256=NwNA-Nxju0I4e1-Msqo_ewJLRcjJjEMiVs2bbfzoMCg,283
2
- mkdocs/__version__.py,sha256=y7OAtBTvz302kS_lnppuG9xWGpwIuMUpU4-ayC_CP8A,46
3
- mkdocs/mkdocs.py,sha256=RnJ8wj2vzozAEqD-X5JMxRoP2wi-uWBC8NH7_DF1Slg,8677
4
- mkdocs/extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- mkdocs/extensions/relative_urls.py,sha256=woA0EUuCXa10wt6C0VCjYnY7jO-fj-wd9uOVU20D96U,1950
6
- mkdocs/extensions/short_codes.py,sha256=I2SwGMcG9OT_vpkJwPI8cHBTkwQAjSPZmoQKfctsHn4,950
7
- mkdocs/extensions/strike_thru.py,sha256=GrCbfMrHz_2Vlh3E572EQYOSDzEGym34pkHElzF2HZY,577
8
- mkdocs/theme/base.html,sha256=xB9VAAgy6zwucGedwTfdhigwNu_lhY3OKiY4aSsN6ZQ,3471
9
- mkdocs-2.0.dev3.dist-info/METADATA,sha256=KerzpRlQfNrRd1Ocu8w5tpEkXPdEyPNgGWyYJwpfzdU,729
10
- mkdocs-2.0.dev3.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
11
- mkdocs-2.0.dev3.dist-info/entry_points.txt,sha256=5PqBrzYJLZ9-yQ0djvENWOQ-0x6Xj30JYNSzM_m70ZU,38
12
- mkdocs-2.0.dev3.dist-info/RECORD,,