rolfedh-doc-utils 0.1.8__py3-none-any.whl → 0.1.10__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.
- doc_utils/extract_link_attributes.py +453 -0
- doc_utils/format_asciidoc_spacing.py +222 -0
- doc_utils/replace_link_attributes.py +168 -0
- extract_link_attributes.py +93 -0
- format_asciidoc_spacing.py +42 -232
- replace_link_attributes.py +186 -0
- {rolfedh_doc_utils-0.1.8.dist-info → rolfedh_doc_utils-0.1.10.dist-info}/METADATA +3 -1
- rolfedh_doc_utils-0.1.10.dist-info/RECORD +23 -0
- {rolfedh_doc_utils-0.1.8.dist-info → rolfedh_doc_utils-0.1.10.dist-info}/entry_points.txt +2 -0
- {rolfedh_doc_utils-0.1.8.dist-info → rolfedh_doc_utils-0.1.10.dist-info}/top_level.txt +2 -0
- rolfedh_doc_utils-0.1.8.dist-info/RECORD +0 -18
- {rolfedh_doc_utils-0.1.8.dist-info → rolfedh_doc_utils-0.1.10.dist-info}/WHEEL +0 -0
- {rolfedh_doc_utils-0.1.8.dist-info → rolfedh_doc_utils-0.1.10.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
replace-link-attributes - Replace AsciiDoc attributes within link URLs with their actual values.
|
|
4
|
+
|
|
5
|
+
This script finds and replaces attribute references (like {attribute-name}) that appear
|
|
6
|
+
in the URL portion of AsciiDoc link macros (link: and xref:) with their resolved values
|
|
7
|
+
from attributes.adoc. Link text is preserved unchanged.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import argparse
|
|
11
|
+
import sys
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import Optional
|
|
14
|
+
|
|
15
|
+
from doc_utils.replace_link_attributes import (
|
|
16
|
+
find_attributes_files,
|
|
17
|
+
load_attributes,
|
|
18
|
+
resolve_nested_attributes,
|
|
19
|
+
replace_link_attributes_in_file,
|
|
20
|
+
find_adoc_files
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def prompt_for_attributes_file(attributes_files: list[Path]) -> Optional[Path]:
|
|
25
|
+
"""Prompt user to select or specify attributes file."""
|
|
26
|
+
if not attributes_files:
|
|
27
|
+
print("No attributes.adoc files found in the repository.")
|
|
28
|
+
response = input("Enter the path to your attributes.adoc file (or 'q' to quit): ").strip()
|
|
29
|
+
if response.lower() == 'q':
|
|
30
|
+
return None
|
|
31
|
+
path = Path(response)
|
|
32
|
+
if path.exists() and path.is_file():
|
|
33
|
+
return path
|
|
34
|
+
else:
|
|
35
|
+
print(f"Error: File not found: {response}")
|
|
36
|
+
return None
|
|
37
|
+
|
|
38
|
+
if len(attributes_files) == 1:
|
|
39
|
+
file_path = attributes_files[0]
|
|
40
|
+
response = input(f"Found attributes file: {file_path}\nUse this file? (y/n/q): ").strip().lower()
|
|
41
|
+
if response == 'y':
|
|
42
|
+
return file_path
|
|
43
|
+
elif response == 'q':
|
|
44
|
+
return None
|
|
45
|
+
else:
|
|
46
|
+
response = input("Enter the path to your attributes.adoc file (or 'q' to quit): ").strip()
|
|
47
|
+
if response.lower() == 'q':
|
|
48
|
+
return None
|
|
49
|
+
path = Path(response)
|
|
50
|
+
if path.exists() and path.is_file():
|
|
51
|
+
return path
|
|
52
|
+
else:
|
|
53
|
+
print(f"Error: File not found: {response}")
|
|
54
|
+
return None
|
|
55
|
+
|
|
56
|
+
# Multiple files found
|
|
57
|
+
print("\nFound multiple attributes.adoc files:")
|
|
58
|
+
for i, file_path in enumerate(attributes_files, 1):
|
|
59
|
+
print(f" {i}. {file_path}")
|
|
60
|
+
print(f" {len(attributes_files) + 1}. Enter custom path")
|
|
61
|
+
|
|
62
|
+
while True:
|
|
63
|
+
response = input(f"\nSelect option (1-{len(attributes_files) + 1}) or 'q' to quit: ").strip()
|
|
64
|
+
if response.lower() == 'q':
|
|
65
|
+
return None
|
|
66
|
+
|
|
67
|
+
try:
|
|
68
|
+
choice = int(response)
|
|
69
|
+
if 1 <= choice <= len(attributes_files):
|
|
70
|
+
return attributes_files[choice - 1]
|
|
71
|
+
elif choice == len(attributes_files) + 1:
|
|
72
|
+
response = input("Enter the path to your attributes.adoc file: ").strip()
|
|
73
|
+
path = Path(response)
|
|
74
|
+
if path.exists() and path.is_file():
|
|
75
|
+
return path
|
|
76
|
+
else:
|
|
77
|
+
print(f"Error: File not found: {response}")
|
|
78
|
+
else:
|
|
79
|
+
print(f"Invalid choice. Please enter a number between 1 and {len(attributes_files) + 1}")
|
|
80
|
+
except ValueError:
|
|
81
|
+
print("Invalid input. Please enter a number.")
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def main():
|
|
85
|
+
parser = argparse.ArgumentParser(
|
|
86
|
+
description='Replace AsciiDoc attributes within link macros with their actual values.'
|
|
87
|
+
)
|
|
88
|
+
parser.add_argument(
|
|
89
|
+
'--dry-run', '-n',
|
|
90
|
+
action='store_true',
|
|
91
|
+
help='Show what would be changed without making actual modifications'
|
|
92
|
+
)
|
|
93
|
+
parser.add_argument(
|
|
94
|
+
'--path', '-p',
|
|
95
|
+
type=str,
|
|
96
|
+
default='.',
|
|
97
|
+
help='Repository path to search (default: current directory)'
|
|
98
|
+
)
|
|
99
|
+
parser.add_argument(
|
|
100
|
+
'--attributes-file', '-a',
|
|
101
|
+
type=str,
|
|
102
|
+
help='Path to attributes.adoc file (skips interactive selection)'
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
args = parser.parse_args()
|
|
106
|
+
|
|
107
|
+
# Determine repository root
|
|
108
|
+
repo_root = Path(args.path).resolve()
|
|
109
|
+
|
|
110
|
+
if not repo_root.exists() or not repo_root.is_dir():
|
|
111
|
+
print(f"Error: Directory not found: {repo_root}")
|
|
112
|
+
sys.exit(1)
|
|
113
|
+
|
|
114
|
+
print(f"{'DRY RUN MODE - ' if args.dry_run else ''}Searching in: {repo_root}")
|
|
115
|
+
|
|
116
|
+
# Find or get attributes file
|
|
117
|
+
if args.attributes_file:
|
|
118
|
+
attributes_file = Path(args.attributes_file)
|
|
119
|
+
if not attributes_file.exists():
|
|
120
|
+
print(f"Error: Specified attributes file not found: {attributes_file}")
|
|
121
|
+
sys.exit(1)
|
|
122
|
+
else:
|
|
123
|
+
print("\nSearching for attributes.adoc files...")
|
|
124
|
+
attributes_files = find_attributes_files(repo_root)
|
|
125
|
+
attributes_file = prompt_for_attributes_file(attributes_files)
|
|
126
|
+
|
|
127
|
+
if not attributes_file:
|
|
128
|
+
print("Operation cancelled.")
|
|
129
|
+
sys.exit(0)
|
|
130
|
+
|
|
131
|
+
print(f"\nLoading attributes from: {attributes_file}")
|
|
132
|
+
attributes = load_attributes(attributes_file)
|
|
133
|
+
|
|
134
|
+
if not attributes:
|
|
135
|
+
print("No attributes found in the file.")
|
|
136
|
+
sys.exit(1)
|
|
137
|
+
|
|
138
|
+
print(f"Found {len(attributes)} attributes")
|
|
139
|
+
|
|
140
|
+
# Resolve nested references
|
|
141
|
+
print("Resolving nested attribute references...")
|
|
142
|
+
attributes = resolve_nested_attributes(attributes)
|
|
143
|
+
|
|
144
|
+
# Find all AsciiDoc files
|
|
145
|
+
print(f"\nSearching for *.adoc files in {repo_root}")
|
|
146
|
+
adoc_files = find_adoc_files(repo_root)
|
|
147
|
+
|
|
148
|
+
# Exclude the attributes file itself
|
|
149
|
+
adoc_files = [f for f in adoc_files if f != attributes_file]
|
|
150
|
+
|
|
151
|
+
print(f"Found {len(adoc_files)} AsciiDoc files to process")
|
|
152
|
+
|
|
153
|
+
if args.dry_run:
|
|
154
|
+
print("\n*** DRY RUN MODE - No files will be modified ***\n")
|
|
155
|
+
|
|
156
|
+
# Process each file
|
|
157
|
+
total_replacements = 0
|
|
158
|
+
files_modified = 0
|
|
159
|
+
|
|
160
|
+
for file_path in adoc_files:
|
|
161
|
+
replacements = replace_link_attributes_in_file(file_path, attributes, args.dry_run)
|
|
162
|
+
if replacements > 0:
|
|
163
|
+
rel_path = file_path.relative_to(repo_root)
|
|
164
|
+
prefix = "[DRY RUN] " if args.dry_run else ""
|
|
165
|
+
print(f" {prefix}Modified {rel_path}: {replacements} replacements")
|
|
166
|
+
total_replacements += replacements
|
|
167
|
+
files_modified += 1
|
|
168
|
+
|
|
169
|
+
# Summary
|
|
170
|
+
print(f"\nSummary:")
|
|
171
|
+
if args.dry_run:
|
|
172
|
+
print(f" Would modify {files_modified} files")
|
|
173
|
+
print(f" Would make {total_replacements} replacements")
|
|
174
|
+
print("\nRun without --dry-run to apply changes.")
|
|
175
|
+
else:
|
|
176
|
+
print(f" Total files modified: {files_modified}")
|
|
177
|
+
print(f" Total replacements: {total_replacements}")
|
|
178
|
+
|
|
179
|
+
if total_replacements == 0:
|
|
180
|
+
print("\nNo attribute references found within link macros.")
|
|
181
|
+
else:
|
|
182
|
+
print("\nReplacement complete!")
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
if __name__ == '__main__':
|
|
186
|
+
main()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rolfedh-doc-utils
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.10
|
|
4
4
|
Summary: CLI tools for AsciiDoc documentation projects
|
|
5
5
|
Author: Rolfe Dlugy-Hegwer
|
|
6
6
|
License: MIT License
|
|
@@ -79,6 +79,8 @@ pip install -e .
|
|
|
79
79
|
|
|
80
80
|
| Tool | Description | Usage |
|
|
81
81
|
|------|-------------|-------|
|
|
82
|
+
| **`extract-link-attributes`** | Extracts link/xref macros with attributes into reusable definitions | `extract-link-attributes --dry-run` |
|
|
83
|
+
| **`replace-link-attributes`** | Resolves Vale LinkAttribute issues by replacing attributes in link URLs | `replace-link-attributes --dry-run` |
|
|
82
84
|
| **`format-asciidoc-spacing`** | Standardizes spacing after headings and around includes | `format-asciidoc-spacing --dry-run modules/` |
|
|
83
85
|
| **`check-scannability`** | Analyzes readability (sentence/paragraph length) | `check-scannability --max-words 25` |
|
|
84
86
|
| **`archive-unused-files`** | Finds and archives unreferenced .adoc files | `archive-unused-files` (preview)<br>`archive-unused-files --archive` (execute) |
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
archive_unused_files.py,sha256=KMC5a1WL3rZ5owoVnncvfpT1YeMKbVXq9giHvadDgbM,1936
|
|
2
|
+
archive_unused_images.py,sha256=PG2o3haovYckgfhoPhl6KRG_a9czyZuqlLkzkupKTCY,1526
|
|
3
|
+
check_scannability.py,sha256=gcM-vFXKHGP_yFBz7-V5xbXWhIMmtMzBYIGwP9CFbzI,5140
|
|
4
|
+
extract_link_attributes.py,sha256=utDM1FE-VEr649HhIH5BreXvxDNLnnAJO9dB5rs5f9Q,2535
|
|
5
|
+
find_unused_attributes.py,sha256=fk-K32eoCVHxoj7RiBNgSmX1arBLuwYfdSAOMc-wIx0,1677
|
|
6
|
+
format_asciidoc_spacing.py,sha256=ROp-cdMs2_hk8H4z5ljT0iDgGtsiECZ8TVjjcN_oOWE,3874
|
|
7
|
+
replace_link_attributes.py,sha256=vg_aufw7dKXvh_epCKRNq_hEBMU_9crZ_JyJPpxSMNk,6454
|
|
8
|
+
doc_utils/__init__.py,sha256=qqZR3lohzkP63soymrEZPBGzzk6-nFzi4_tSffjmu_0,74
|
|
9
|
+
doc_utils/extract_link_attributes.py,sha256=qBpJuTXNrhy15klpqC0iELZzcSLztEzMSmhEnKyQZT0,15574
|
|
10
|
+
doc_utils/file_utils.py,sha256=fpTh3xx759sF8sNocdn_arsP3KAv8XA6cTQTAVIZiZg,4247
|
|
11
|
+
doc_utils/format_asciidoc_spacing.py,sha256=XnVJekaj39aDzjV3xFKl58flM41AaJzejxNYJIIAMz0,10139
|
|
12
|
+
doc_utils/replace_link_attributes.py,sha256=kBiePbxjQn3O2rzqmYY8Mqy_mJgZ6yw048vSZ5SSB5E,6587
|
|
13
|
+
doc_utils/scannability.py,sha256=XwlmHqDs69p_V36X7DLjPTy0DUoLszSGqYjJ9wE-3hg,982
|
|
14
|
+
doc_utils/topic_map_parser.py,sha256=tKcIO1m9r2K6dvPRGue58zqMr0O2zKU1gnZMzEE3U6o,4571
|
|
15
|
+
doc_utils/unused_adoc.py,sha256=2cbqcYr1os2EhETUU928BlPRlsZVSdI00qaMhqjSIqQ,5263
|
|
16
|
+
doc_utils/unused_attributes.py,sha256=HBgmHelqearfWl3TTC2bZGiJytjLADIgiGQUNKqXXPg,1847
|
|
17
|
+
doc_utils/unused_images.py,sha256=nqn36Bbrmon2KlGlcaruNjJJvTQ8_9H0WU9GvCW7rW8,1456
|
|
18
|
+
rolfedh_doc_utils-0.1.10.dist-info/licenses/LICENSE,sha256=vLxtwMVOJA_hEy8b77niTkdmQI9kNJskXHq0dBS36e0,1075
|
|
19
|
+
rolfedh_doc_utils-0.1.10.dist-info/METADATA,sha256=Kk1Ur-SbE2XIP55NJ7Y5oVB-KNScnlADwmZyFSthTXo,7180
|
|
20
|
+
rolfedh_doc_utils-0.1.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
21
|
+
rolfedh_doc_utils-0.1.10.dist-info/entry_points.txt,sha256=aQtQRDwcdDN-VLBCnQBfmoozzQiaCUZ9dqcLLv8fCkM,381
|
|
22
|
+
rolfedh_doc_utils-0.1.10.dist-info/top_level.txt,sha256=ILTc2mA4sHdDp0GvKC8JXO1I_DBP7vvF5hn-PFkMcL8,167
|
|
23
|
+
rolfedh_doc_utils-0.1.10.dist-info/RECORD,,
|
|
@@ -2,5 +2,7 @@
|
|
|
2
2
|
archive-unused-files = archive_unused_files:main
|
|
3
3
|
archive-unused-images = archive_unused_images:main
|
|
4
4
|
check-scannability = check_scannability:main
|
|
5
|
+
extract-link-attributes = extract_link_attributes:main
|
|
5
6
|
find-unused-attributes = find_unused_attributes:main
|
|
6
7
|
format-asciidoc-spacing = format_asciidoc_spacing:main
|
|
8
|
+
replace-link-attributes = replace_link_attributes:main
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
archive_unused_files.py,sha256=KMC5a1WL3rZ5owoVnncvfpT1YeMKbVXq9giHvadDgbM,1936
|
|
2
|
-
archive_unused_images.py,sha256=PG2o3haovYckgfhoPhl6KRG_a9czyZuqlLkzkupKTCY,1526
|
|
3
|
-
check_scannability.py,sha256=gcM-vFXKHGP_yFBz7-V5xbXWhIMmtMzBYIGwP9CFbzI,5140
|
|
4
|
-
find_unused_attributes.py,sha256=fk-K32eoCVHxoj7RiBNgSmX1arBLuwYfdSAOMc-wIx0,1677
|
|
5
|
-
format_asciidoc_spacing.py,sha256=Jy_V8c03KGRPJxu4uPdDuMsFg-Q-4AGD9BdkGnApUu8,13241
|
|
6
|
-
doc_utils/__init__.py,sha256=qqZR3lohzkP63soymrEZPBGzzk6-nFzi4_tSffjmu_0,74
|
|
7
|
-
doc_utils/file_utils.py,sha256=fpTh3xx759sF8sNocdn_arsP3KAv8XA6cTQTAVIZiZg,4247
|
|
8
|
-
doc_utils/scannability.py,sha256=XwlmHqDs69p_V36X7DLjPTy0DUoLszSGqYjJ9wE-3hg,982
|
|
9
|
-
doc_utils/topic_map_parser.py,sha256=tKcIO1m9r2K6dvPRGue58zqMr0O2zKU1gnZMzEE3U6o,4571
|
|
10
|
-
doc_utils/unused_adoc.py,sha256=2cbqcYr1os2EhETUU928BlPRlsZVSdI00qaMhqjSIqQ,5263
|
|
11
|
-
doc_utils/unused_attributes.py,sha256=HBgmHelqearfWl3TTC2bZGiJytjLADIgiGQUNKqXXPg,1847
|
|
12
|
-
doc_utils/unused_images.py,sha256=nqn36Bbrmon2KlGlcaruNjJJvTQ8_9H0WU9GvCW7rW8,1456
|
|
13
|
-
rolfedh_doc_utils-0.1.8.dist-info/licenses/LICENSE,sha256=vLxtwMVOJA_hEy8b77niTkdmQI9kNJskXHq0dBS36e0,1075
|
|
14
|
-
rolfedh_doc_utils-0.1.8.dist-info/METADATA,sha256=KrjqTRhF_B26ZNt37SZXReMcV4-ztpy1aWHJepYxMDE,6891
|
|
15
|
-
rolfedh_doc_utils-0.1.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
16
|
-
rolfedh_doc_utils-0.1.8.dist-info/entry_points.txt,sha256=dA-u4qlxKcewUAOFgaeW1NUIrkhsVknuwFuGTn1-84w,271
|
|
17
|
-
rolfedh_doc_utils-0.1.8.dist-info/top_level.txt,sha256=WrYqTa4wbjRPMUl2hgJBfP734XsXLkhbnzUublx8S0s,119
|
|
18
|
-
rolfedh_doc_utils-0.1.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|