afterpython 0.3.7__py3-none-any.whl → 0.3.9__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.
@@ -4,17 +4,12 @@ import afterpython as ap
4
4
  from afterpython.const import CONTENT_TYPES, PLACEHOLDER_INDEX_MARKER
5
5
 
6
6
 
7
- def _legacy_placeholder_content(content_type: str) -> str:
8
- return f"""---
9
- title: ← {content_type.capitalize()}
10
- ---
11
-
12
- This is a placeholder index page. The actual {content_type} landing page is rendered by SvelteKit.
13
- """
14
-
15
-
16
- def _legacy_welcome_content(content_type: str) -> str:
17
- return f"""# Welcome to AfterPython
7
+ def _placeholder_content(content_type: str) -> str:
8
+ """Current placeholder body. Marker is an HTML comment so it embeds invisibly;
9
+ _is_afterpython_placeholder_index keys off it to tell our files apart from
10
+ user-authored ones."""
11
+ return f"""{PLACEHOLDER_INDEX_MARKER}
12
+ # Welcome to AfterPython
18
13
 
19
14
  Welcome to your project's {content_type}! This is a starter page to help you get started.
20
15
 
@@ -35,6 +30,19 @@ Start building your amazing project! 🚀
35
30
  """
36
31
 
37
32
 
33
+ def _legacy_placeholder_content(content_type: str) -> str:
34
+ """Frozen fingerprint of the arrow-stub placeholder written between commits
35
+ 49f30c1 and 3a560e2 (no marker). Kept solely so projects built in that window
36
+ are still recognized as ours and cleaned up rather than blocking with the
37
+ 'reserved' error. Do not edit — that would break recognition."""
38
+ return f"""---
39
+ title: ← {content_type.capitalize()}
40
+ ---
41
+
42
+ This is a placeholder index page. The actual {content_type} landing page is rendered by SvelteKit.
43
+ """
44
+
45
+
38
46
  def _is_afterpython_placeholder_index(index_md, content_type: str) -> bool:
39
47
  """Return True only for non-doc index.md files generated by AfterPython."""
40
48
  content = index_md.read_text(encoding="utf-8", errors="ignore")
@@ -43,7 +51,6 @@ def _is_afterpython_placeholder_index(index_md, content_type: str) -> bool:
43
51
  return (
44
52
  PLACEHOLDER_INDEX_MARKER in content
45
53
  or normalized_content == _legacy_placeholder_content(content_type).strip()
46
- or normalized_content == _legacy_welcome_content(content_type).strip()
47
54
  )
48
55
 
49
56
 
@@ -76,25 +83,15 @@ def create_placeholder_index_md_files():
76
83
  )
77
84
  continue
78
85
 
79
- content_path = ap.paths.afterpython_path / content_type
80
- myst_yml_path = content_path / "myst.yml"
81
-
82
- # Prepend index.md to TOC in myst.yml
83
- if myst_yml_path.exists():
84
- # Create placeholder index.md file
85
- _write_index_file(content_type)
86
- myst_data = read_yaml(myst_yml_path) or {}
87
- toc = myst_data.get("project", {}).get("toc", [])
86
+ _write_index_file(content_type)
88
87
 
89
- # Check if index.md is already first in TOC
90
- if not toc or toc[0].get("file") != "index.md":
91
- # Prepend index.md to TOC in myst.yml
92
- new_toc = [{"file": "index.md"}, *toc]
93
- if "project" not in myst_data:
94
- myst_data["project"] = {}
95
- myst_data["project"]["toc"] = new_toc
96
- write_yaml(myst_yml_path, myst_data)
97
- click.echo(f"Added index.md to TOC in {myst_yml_path}")
88
+ # Prepend index.md to TOC in myst.yml (skip if already first).
89
+ myst_data = read_yaml(myst_yml_path) or {}
90
+ toc = myst_data.get("project", {}).get("toc", [])
91
+ if not toc or toc[0].get("file") != "index.md":
92
+ myst_data.setdefault("project", {})["toc"] = [{"file": "index.md"}, *toc]
93
+ write_yaml(myst_yml_path, myst_data)
94
+ click.echo(f"Added index.md to TOC in {myst_yml_path}")
98
95
 
99
96
 
100
97
  def delete_placeholder_index_md_files():
@@ -62,6 +62,7 @@ def build_metadata():
62
62
  # slash form that the Svelte side can hand straight to `asset()`.
63
63
  metadata_json["logo"] = _resolve_logo_path(website.get("logo", ""))
64
64
  metadata_json["logo_dark"] = _resolve_logo_path(website.get("logo_dark", ""))
65
+ metadata_json["favicon"] = _resolve_logo_path(website.get("favicon", ""))
65
66
 
66
67
  with open(build_path / "metadata.json", "w") as f:
67
68
  json.dump(metadata_json, f, indent=2)
@@ -171,7 +171,13 @@ def postbuild(dev_build: bool = False):
171
171
  print(f"Moved: {source} to {destination}")
172
172
 
173
173
  build_content_json()
174
- delete_placeholder_index_md_files()
174
+ # In dev mode the MyST `start` server is watching these files. Deleting
175
+ # them here would make MyST re-index without the placeholder and revert
176
+ # to using the first content file as the section index — exactly what
177
+ # the placeholder was created to prevent. `ap dev` cleans them up in
178
+ # its `finally` block after MyST has been shut down.
179
+ if not dev_build:
180
+ delete_placeholder_index_md_files()
175
181
 
176
182
  website_static = ap.paths.website_path / "static"
177
183
  website_static.mkdir(parents=True, exist_ok=True)
@@ -11,6 +11,7 @@ import time
11
11
  import click
12
12
  from click.exceptions import Exit
13
13
 
14
+ from afterpython.builders import delete_placeholder_index_md_files
14
15
  from afterpython.cli.commands.build import postbuild, prebuild
15
16
  from afterpython.const import CONTENT_TYPES
16
17
  from afterpython.utils import find_available_port, find_node_env
@@ -218,3 +219,6 @@ def dev(
218
219
  pass
219
220
  finally:
220
221
  cleanup_processes()
222
+ # Now that MyST watchers are gone, clean up the placeholders
223
+ # postbuild() intentionally left behind for dev mode.
224
+ delete_placeholder_index_md_files()
afterpython/tools/myst.py CHANGED
@@ -143,14 +143,11 @@ def _write_index_file(content_type: tContentType):
143
143
  f"and update the reference in afterpython/{content_type}/myst.yml."
144
144
  )
145
145
 
146
- index_content = f"""---
147
- title: ← {content_type.capitalize()}
148
- ---
146
+ # Lazy import to avoid the circular dep with builders/index_md.py, which
147
+ # already lazy-imports _write_index_file from this module.
148
+ from afterpython.builders.index_md import _placeholder_content
149
149
 
150
- {PLACEHOLDER_INDEX_MARKER}
151
-
152
- This is a placeholder index page. The actual {content_type} landing page is rendered by SvelteKit.
153
- """
150
+ index_content = _placeholder_content(content_type)
154
151
  index_file.write_text(index_content)
155
152
  return index_file
156
153
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: afterpython
3
- Version: 0.3.7
3
+ Version: 0.3.9
4
4
  Summary: CLI tool to streamline Python package maintenance and generate a dedicated project website
5
5
  Keywords: package-maintenance,project-website,static-site-generator,developer-tools,documentation,cli-tool,ci/cd,mystmd,semantic-release,python-packaging
6
6
  Author: Stephen Yau
@@ -7,22 +7,22 @@ afterpython/builders/__init__.py,sha256=H7f9mFKXofWOAC3hkrxiFzvW5NziF8wYyduUBykH
7
7
  afterpython/builders/build_pdoc.py,sha256=rasjCtTah5GsZYokqU--Fp3bvTEf464ievENfOoANOk,2040
8
8
  afterpython/builders/content_json.py,sha256=-LTkeA8oA6XEudc2b1H7U0-UwcJlHn7xgICeweMYrG0,4805
9
9
  afterpython/builders/faq_json.py,sha256=mMfFepRBL_1QYO0tQ6orf5ESo2LVntk55nfFzencViM,1193
10
- afterpython/builders/index_md.py,sha256=M4TNqrMl9_7HKiu11VOGiYvgffBQp3ZZbgLvlczZAVA,5998
10
+ afterpython/builders/index_md.py,sha256=ZpBA1FIHgw9MXD8kRaq2OBaEAKnf94_sJmB2cG68iag,6021
11
11
  afterpython/builders/jupyter_notebook.py,sha256=8yjgwWBaHfEzvN90j4biR6-RaTUHeIQ59h4NKethHOk,9693
12
12
  afterpython/builders/llms_txt.py,sha256=9x-B1i1buTDJt4zGs8nugyto_pI5QIp7WUBcv-zpcso,9226
13
13
  afterpython/builders/marimo_notebook.py,sha256=cIah_ly67tTj4j1y7yL19MRQ9NN6vESmS2JKMsEuaA0,5386
14
14
  afterpython/builders/markdown.py,sha256=0ExfRqvOTWsgUkAVaGGNkiNDtNedRr7JR1yTGxpbsmA,8736
15
- afterpython/builders/metadata.py,sha256=_GNXcrVM5mFvRGrPt6Liqy-D2jBzfIZz4nI1kOD2uJ4,3752
15
+ afterpython/builders/metadata.py,sha256=EueKoYWM__Hb9MwX0KYejxJvouoaAxD1oz9AP-Na-ZI,3830
16
16
  afterpython/builders/url_md.py,sha256=uuW3YCyphd-Qvl9Yopv48utu6y1tyfJHNc25sS-O6Yw,3526
17
17
  afterpython/cli/__init__.py,sha256=G4AB-rllhmr7tURFc5cXJfkjZZ2bXtMBg3oy4zUGEFw,84
18
18
  afterpython/cli/commands/add.py,sha256=Ppp4msdvOwN9_-fdG5-b0-IV9p0Eef9CiIEU3srUjYk,1792
19
- afterpython/cli/commands/build.py,sha256=h0AaZuhjuxD_2Iu_CHD-3-OMBbi-ncAYuMUIR2pha1k,11798
19
+ afterpython/cli/commands/build.py,sha256=gKrpRIy1DNAlnP6o0PBZyis8arjAN6YEauhw2uVkO9c,12182
20
20
  afterpython/cli/commands/bump.py,sha256=9fR-wShNKhXbW2JgMExPlyI2n14TfQOtowAuALp-N-8,4122
21
21
  afterpython/cli/commands/check.py,sha256=lrPaVThAwxxnczu-VOZT7dd7aKjstnMQfX9UpZY3Lxs,1058
22
22
  afterpython/cli/commands/clean.py,sha256=havP43ZC1AKFzvscsRMF_to6TvOwruxGA5qzr6dMHvg,2529
23
23
  afterpython/cli/commands/commit.py,sha256=9QOKyt4tfTJzZEdHEPAdpUc4stYMSvG3-31uADuBxn4,1420
24
24
  afterpython/cli/commands/commitizen.py,sha256=H3jewz4VkZi5FYTWw3USVM3XosRx12kPShOQGxD3LNM,842
25
- afterpython/cli/commands/dev.py,sha256=LVv6WUB1RNe8w7yAQS_1TQEEn_wklbJOuduapYlg2FA,7039
25
+ afterpython/cli/commands/dev.py,sha256=M04QgGTksIFMDglo2iUyTvFWiE-o5o4JsXqLu9DGoXY,7281
26
26
  afterpython/cli/commands/format.py,sha256=VFwCG9KDTF6j4Y_Ewp4_RpS8uNBQNOAj9HU_G97my5A,710
27
27
  afterpython/cli/commands/init.py,sha256=t-SKqmPOSpQu4821PNar0bQ6EjTX3qwQr2trAULns94,3877
28
28
  afterpython/cli/commands/init_branch_rules.py,sha256=fzAm8D5qbW3u4bEMpqPuRgO-0akuCGG7pu09JlKhYn4,243
@@ -54,12 +54,12 @@ afterpython/tools/_git.py,sha256=aO-qDEQ4OevD_B74DYKK4nQKYeiaS1BXmYc8paJRfbQ,377
54
54
  afterpython/tools/branch_rules.py,sha256=ciQ2H2YBnoCZu_plyVeIHzf2FcAILRFhpjzOR2_IfJg,3159
55
55
  afterpython/tools/commitizen.py,sha256=ZO1qHmzUU0myd85tncv76WtIR7DB_AoQGSUvaf78Ohg,438
56
56
  afterpython/tools/github_actions.py,sha256=0xzOc41QF1PKagD1CW7BAt_Rugy0KCEx_KfcrPKVl3c,3168
57
- afterpython/tools/myst.py,sha256=03m1bBKHxcDgruwrNjf7zAu5eH6TVDvsXSd936eIGF4,8586
57
+ afterpython/tools/myst.py,sha256=UbtcCUbu_zMYZA00LptO25VKNi7GOodeNVuiGgi1320,8646
58
58
  afterpython/tools/pre_commit.py,sha256=oNsrUkPI13rSSBSyhyTTKPnQGhDxLIPYhxu6kL0fDmo,1206
59
59
  afterpython/tools/pyproject.py,sha256=hz-DOf-pkGBF2m_RqEZipAaO-NDbsLxrrc65LWAIwLA,3698
60
60
  afterpython/utils.py,sha256=fVa3jIzCvhn7QA7N0M6d_pvojpPFrN-hae8trUYhPKU,11701
61
61
  afterpython/version.py,sha256=hihRV1S-gc1m46OaXD32ikkEkqzs-Gtq7AcAqOQV-wY,1603
62
- afterpython-0.3.7.dist-info/WHEEL,sha256=f5fWSvWsg5Knq5GWa6t1nJIug0Tqo69GqAWD_9LbBKw,81
63
- afterpython-0.3.7.dist-info/entry_points.txt,sha256=roa0PDgBueM1JPbRG0G2OSxzaN394OUL_oS9iEwVLBc,80
64
- afterpython-0.3.7.dist-info/METADATA,sha256=838abK-PJzhIAb2gK1tamV9PysHdyrZM5MwdEqFKyrk,6180
65
- afterpython-0.3.7.dist-info/RECORD,,
62
+ afterpython-0.3.9.dist-info/WHEEL,sha256=f5fWSvWsg5Knq5GWa6t1nJIug0Tqo69GqAWD_9LbBKw,81
63
+ afterpython-0.3.9.dist-info/entry_points.txt,sha256=roa0PDgBueM1JPbRG0G2OSxzaN394OUL_oS9iEwVLBc,80
64
+ afterpython-0.3.9.dist-info/METADATA,sha256=C7LnowtwFEhNTLvjddSpDfcUx3Lv7LWAyHghKBPIr_Q,6180
65
+ afterpython-0.3.9.dist-info/RECORD,,