@voodocs/cli 2.5.2 → 3.0.0
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.
- package/CHANGELOG.md +156 -235
- package/README.md +215 -399
- package/lib/cli/__init__.py +1 -3
- package/lib/cli/init.py +11 -13
- package/lib/darkarts/annotations/darkarts_parser.py +159 -142
- package/lib/darkarts/annotations/darkarts_parser_v2.py.bak +238 -0
- package/lib/darkarts/companion_files.py +62 -9
- package/lib/darkarts/context/ai_instructions.py +385 -571
- package/lib/darkarts/context/ai_instructions_v2.py.bak +741 -0
- package/lib/darkarts/darkarts_abbreviations.py +324 -0
- package/lib/darkarts/darkarts_parser_v3.py +486 -0
- package/lib/darkarts/darkarts_patterns.py +249 -0
- package/lib/darkarts/darkarts_symbols.py +276 -0
- package/lib/darkarts/plugins/voodocs/documentation_generator.py +31 -2
- package/lib/darkarts/validation/semantic.py +135 -18
- package/package.json +5 -4
- package/lib/cli/convert.py +0 -131
- package/lib/darkarts/voodocs_lite_dict.py +0 -216
- package/lib/darkarts/voodocs_lite_dict_v2.py +0 -198
- package/lib/darkarts/voodocs_lite_parser.py +0 -343
|
@@ -148,20 +148,42 @@ class ImportExtractor(ast.NodeVisitor):
|
|
|
148
148
|
|
|
149
149
|
def extract_imports(file_path: Path) -> Set[str]:
|
|
150
150
|
"""
|
|
151
|
-
Extract all imports from a
|
|
151
|
+
Extract all imports from a source file.
|
|
152
152
|
|
|
153
|
-
|
|
153
|
+
Supports:
|
|
154
|
+
- Python: AST-based parsing
|
|
155
|
+
- TypeScript/JavaScript: Regex-based extraction
|
|
156
|
+
- Other languages: Best-effort regex extraction
|
|
154
157
|
|
|
155
158
|
Args:
|
|
156
|
-
file_path: Path to the
|
|
159
|
+
file_path: Path to the source file
|
|
157
160
|
|
|
158
161
|
Returns:
|
|
159
|
-
Set of top-level module names imported in the file
|
|
162
|
+
Set of top-level module/package names imported in the file
|
|
160
163
|
|
|
161
164
|
Examples:
|
|
162
165
|
>>> extract_imports(Path("myfile.py"))
|
|
163
166
|
{'os', 'sys', 'pathlib', 'typing', 'darkarts'}
|
|
167
|
+
>>> extract_imports(Path("myfile.ts"))
|
|
168
|
+
{'react', 'axios', './utils'}
|
|
164
169
|
"""
|
|
170
|
+
suffix = file_path.suffix.lower()
|
|
171
|
+
|
|
172
|
+
# Python files - use AST parsing
|
|
173
|
+
if suffix == '.py':
|
|
174
|
+
return _extract_python_imports(file_path)
|
|
175
|
+
|
|
176
|
+
# TypeScript/JavaScript files - use regex
|
|
177
|
+
elif suffix in {'.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'}:
|
|
178
|
+
return _extract_js_imports(file_path)
|
|
179
|
+
|
|
180
|
+
# Other languages - best effort
|
|
181
|
+
else:
|
|
182
|
+
return _extract_generic_imports(file_path)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def _extract_python_imports(file_path: Path) -> Set[str]:
|
|
186
|
+
"""Extract imports from Python files using AST."""
|
|
165
187
|
try:
|
|
166
188
|
content = file_path.read_text(encoding='utf-8')
|
|
167
189
|
tree = ast.parse(content, filename=str(file_path))
|
|
@@ -171,15 +193,13 @@ def extract_imports(file_path: Path) -> Set[str]:
|
|
|
171
193
|
|
|
172
194
|
imports = extractor.get_all_imports()
|
|
173
195
|
|
|
174
|
-
# Filter out standard library modules
|
|
175
|
-
# from annotations (optional - can be configured)
|
|
196
|
+
# Filter out standard library modules
|
|
176
197
|
stdlib_to_keep = {
|
|
177
198
|
'typing', 'dataclasses', 'enum', 'abc', 'pathlib',
|
|
178
199
|
'datetime', 'json', 'yaml', 're', 'os', 'sys',
|
|
179
200
|
'time', 'uuid', 'collections', 'itertools', 'functools'
|
|
180
201
|
}
|
|
181
202
|
|
|
182
|
-
# Keep all non-stdlib and explicitly listed stdlib modules
|
|
183
203
|
filtered_imports = {
|
|
184
204
|
imp for imp in imports
|
|
185
205
|
if not _is_stdlib_module(imp) or imp in stdlib_to_keep
|
|
@@ -193,6 +213,69 @@ def extract_imports(file_path: Path) -> Set[str]:
|
|
|
193
213
|
raise ValueError(f"Error parsing {file_path}: {e}")
|
|
194
214
|
|
|
195
215
|
|
|
216
|
+
def _extract_js_imports(file_path: Path) -> Set[str]:
|
|
217
|
+
"""Extract imports from TypeScript/JavaScript files using regex."""
|
|
218
|
+
try:
|
|
219
|
+
content = file_path.read_text(encoding='utf-8')
|
|
220
|
+
imports = set()
|
|
221
|
+
|
|
222
|
+
# Match: import ... from 'module'
|
|
223
|
+
# Match: import ... from "module"
|
|
224
|
+
import_pattern = r"import\s+(?:.*?\s+from\s+)?['\"]([^'\"]+)['\"]"
|
|
225
|
+
for match in re.finditer(import_pattern, content):
|
|
226
|
+
module = match.group(1)
|
|
227
|
+
# Extract package name (ignore relative paths for now)
|
|
228
|
+
if not module.startswith('.'):
|
|
229
|
+
# Get first part of scoped package (@org/pkg) or regular package
|
|
230
|
+
if module.startswith('@'):
|
|
231
|
+
parts = module.split('/')
|
|
232
|
+
if len(parts) >= 2:
|
|
233
|
+
imports.add(f"{parts[0]}/{parts[1]}")
|
|
234
|
+
else:
|
|
235
|
+
imports.add(module.split('/')[0])
|
|
236
|
+
|
|
237
|
+
# Match: require('module')
|
|
238
|
+
require_pattern = r"require\(['\"]([^'\"]+)['\"]\)"
|
|
239
|
+
for match in re.finditer(require_pattern, content):
|
|
240
|
+
module = match.group(1)
|
|
241
|
+
if not module.startswith('.'):
|
|
242
|
+
if module.startswith('@'):
|
|
243
|
+
parts = module.split('/')
|
|
244
|
+
if len(parts) >= 2:
|
|
245
|
+
imports.add(f"{parts[0]}/{parts[1]}")
|
|
246
|
+
else:
|
|
247
|
+
imports.add(module.split('/')[0])
|
|
248
|
+
|
|
249
|
+
return imports
|
|
250
|
+
|
|
251
|
+
except Exception as e:
|
|
252
|
+
raise ValueError(f"Error parsing {file_path}: {e}")
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def _extract_generic_imports(file_path: Path) -> Set[str]:
|
|
256
|
+
"""Best-effort import extraction for other languages."""
|
|
257
|
+
try:
|
|
258
|
+
content = file_path.read_text(encoding='utf-8')
|
|
259
|
+
imports = set()
|
|
260
|
+
|
|
261
|
+
# Generic patterns for various languages
|
|
262
|
+
patterns = [
|
|
263
|
+
r"import\s+['\"]([^'\"]+)['\"]", # Generic import
|
|
264
|
+
r"require\(['\"]([^'\"]+)['\"]\)", # Require
|
|
265
|
+
r"use\s+([\w:]+)", # Rust/Perl
|
|
266
|
+
r"#include\s+[<\"]([^>\"]+)[>\"]" # C/C++
|
|
267
|
+
]
|
|
268
|
+
|
|
269
|
+
for pattern in patterns:
|
|
270
|
+
for match in re.finditer(pattern, content):
|
|
271
|
+
imports.add(match.group(1))
|
|
272
|
+
|
|
273
|
+
return imports
|
|
274
|
+
|
|
275
|
+
except Exception as e:
|
|
276
|
+
return set() # Return empty set on error for generic extraction
|
|
277
|
+
|
|
278
|
+
|
|
196
279
|
def _is_stdlib_module(module_name: str) -> bool:
|
|
197
280
|
"""
|
|
198
281
|
Check if a module is part of Python's standard library.
|
|
@@ -258,10 +341,15 @@ def parse_dependencies(annotation: str) -> Set[str]:
|
|
|
258
341
|
|
|
259
342
|
def extract_annotation(file_path: Path) -> Optional[str]:
|
|
260
343
|
"""
|
|
261
|
-
Extract the @darkarts annotation from
|
|
344
|
+
Extract the @darkarts annotation from any source file.
|
|
345
|
+
|
|
346
|
+
Supports:
|
|
347
|
+
- Python: triple-quote @darkarts docstrings
|
|
348
|
+
- TypeScript/JavaScript: /**@darkarts ... */ block comments
|
|
349
|
+
- Other languages with similar comment syntax
|
|
262
350
|
|
|
263
351
|
Args:
|
|
264
|
-
file_path: Path to the
|
|
352
|
+
file_path: Path to the source file
|
|
265
353
|
|
|
266
354
|
Returns:
|
|
267
355
|
The annotation string, or None if not found
|
|
@@ -269,17 +357,46 @@ def extract_annotation(file_path: Path) -> Optional[str]:
|
|
|
269
357
|
try:
|
|
270
358
|
content = file_path.read_text(encoding='utf-8')
|
|
271
359
|
|
|
272
|
-
#
|
|
273
|
-
if
|
|
274
|
-
|
|
360
|
+
# Python-style docstring
|
|
361
|
+
if '"""@darkarts' in content:
|
|
362
|
+
start_idx = content.find('"""@darkarts')
|
|
363
|
+
end_idx = content.find('"""', start_idx + 3)
|
|
364
|
+
if end_idx != -1:
|
|
365
|
+
return content[start_idx + 3:end_idx]
|
|
366
|
+
|
|
367
|
+
# JavaScript/TypeScript/C-style block comment
|
|
368
|
+
if '/**@darkarts' in content or '/*@darkarts' in content:
|
|
369
|
+
# Find the @darkarts comment
|
|
370
|
+
start_marker = '/**@darkarts' if '/**@darkarts' in content else '/*@darkarts'
|
|
371
|
+
start_idx = content.find(start_marker)
|
|
372
|
+
end_idx = content.find('*/', start_idx)
|
|
373
|
+
if end_idx != -1:
|
|
374
|
+
annotation = content[start_idx + len(start_marker):end_idx]
|
|
375
|
+
return annotation.strip()
|
|
275
376
|
|
|
276
|
-
#
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
377
|
+
# Single-line comment style (less common but supported)
|
|
378
|
+
if '//@darkarts' in content or '#@darkarts' in content:
|
|
379
|
+
lines = content.split('\n')
|
|
380
|
+
annotation_lines = []
|
|
381
|
+
in_annotation = False
|
|
382
|
+
for line in lines:
|
|
383
|
+
if '//@darkarts' in line or '#@darkarts' in line:
|
|
384
|
+
in_annotation = True
|
|
385
|
+
# Extract content after @darkarts
|
|
386
|
+
if '//@darkarts' in line:
|
|
387
|
+
annotation_lines.append(line.split('//@darkarts', 1)[1].strip())
|
|
388
|
+
else:
|
|
389
|
+
annotation_lines.append(line.split('#@darkarts', 1)[1].strip())
|
|
390
|
+
elif in_annotation and (line.strip().startswith('//') or line.strip().startswith('#')):
|
|
391
|
+
# Continue multi-line annotation
|
|
392
|
+
annotation_lines.append(line.strip().lstrip('/#').strip())
|
|
393
|
+
elif in_annotation:
|
|
394
|
+
# End of annotation
|
|
395
|
+
break
|
|
396
|
+
if annotation_lines:
|
|
397
|
+
return '\n'.join(annotation_lines)
|
|
280
398
|
|
|
281
|
-
|
|
282
|
-
return annotation
|
|
399
|
+
return None
|
|
283
400
|
|
|
284
401
|
except Exception as e:
|
|
285
402
|
raise ValueError(f"Error reading {file_path}: {e}")
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voodocs/cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "AI-Native Symbolic Documentation System - The world's first documentation tool using mathematical notation with semantic validation",
|
|
5
5
|
"main": "voodocs_cli.py",
|
|
6
6
|
"bin": {
|
|
@@ -64,9 +64,10 @@
|
|
|
64
64
|
"lib/darkarts/exceptions.py",
|
|
65
65
|
"lib/darkarts/telemetry.py",
|
|
66
66
|
"lib/darkarts/companion_files.py",
|
|
67
|
-
"lib/darkarts/
|
|
68
|
-
"lib/darkarts/
|
|
69
|
-
"lib/darkarts/
|
|
67
|
+
"lib/darkarts/darkarts_abbreviations.py",
|
|
68
|
+
"lib/darkarts/darkarts_patterns.py",
|
|
69
|
+
"lib/darkarts/darkarts_symbols.py",
|
|
70
|
+
"lib/darkarts/darkarts_parser_v3.py",
|
|
70
71
|
"lib/darkarts/priority_analyzer/",
|
|
71
72
|
"lib/darkarts/parsers/typescript/dist/",
|
|
72
73
|
"lib/darkarts/parsers/typescript/src/",
|
package/lib/cli/convert.py
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
"""@darkarts
|
|
2
|
-
⊢cli:convert
|
|
3
|
-
∂{click,pathlib,darkarts.voodocs_lite_parser}
|
|
4
|
-
⚠{python≥3.7,click≥8.0}
|
|
5
|
-
⊨{∀file→converted|skipped,∀error→reported}
|
|
6
|
-
🔒{read-only:source-files}
|
|
7
|
-
⚡{O(n):files}
|
|
8
|
-
"""
|
|
9
|
-
|
|
10
|
-
"""
|
|
11
|
-
VooDocs Convert Command
|
|
12
|
-
|
|
13
|
-
Convert VooDocs annotations between Standard and Lite formats.
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
import click
|
|
17
|
-
from pathlib import Path
|
|
18
|
-
import sys
|
|
19
|
-
|
|
20
|
-
# Import VooDocs Lite parser
|
|
21
|
-
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
22
|
-
from darkarts.voodocs_lite_parser import VooDocsLiteParser
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
@click.command()
|
|
26
|
-
@click.argument(
|
|
27
|
-
'paths',
|
|
28
|
-
nargs=-1,
|
|
29
|
-
type=click.Path(exists=True),
|
|
30
|
-
required=True
|
|
31
|
-
)
|
|
32
|
-
@click.option(
|
|
33
|
-
'--to',
|
|
34
|
-
'target_format',
|
|
35
|
-
type=click.Choice(['lite', 'standard']),
|
|
36
|
-
required=True,
|
|
37
|
-
help='Target format to convert to'
|
|
38
|
-
)
|
|
39
|
-
@click.option(
|
|
40
|
-
'-r', '--recursive',
|
|
41
|
-
is_flag=True,
|
|
42
|
-
help='Recursively process directories'
|
|
43
|
-
)
|
|
44
|
-
@click.option(
|
|
45
|
-
'--dry-run',
|
|
46
|
-
is_flag=True,
|
|
47
|
-
help='Show what would be converted without modifying files'
|
|
48
|
-
)
|
|
49
|
-
@click.option(
|
|
50
|
-
'-v', '--verbose',
|
|
51
|
-
is_flag=True,
|
|
52
|
-
help='Show detailed conversion information'
|
|
53
|
-
)
|
|
54
|
-
def convert(paths, target_format, recursive, dry_run, verbose):
|
|
55
|
-
"""
|
|
56
|
-
Convert VooDocs annotations between Standard and Lite formats.
|
|
57
|
-
|
|
58
|
-
Examples:
|
|
59
|
-
voodocs convert src/ --to lite
|
|
60
|
-
voodocs convert src/ --to standard --recursive
|
|
61
|
-
voodocs convert file.ts --to lite --dry-run
|
|
62
|
-
"""
|
|
63
|
-
parser = VooDocsLiteParser()
|
|
64
|
-
|
|
65
|
-
converted_count = 0
|
|
66
|
-
skipped_count = 0
|
|
67
|
-
error_count = 0
|
|
68
|
-
|
|
69
|
-
for path_str in paths:
|
|
70
|
-
path = Path(path_str)
|
|
71
|
-
|
|
72
|
-
if path.is_file():
|
|
73
|
-
files = [path]
|
|
74
|
-
elif path.is_dir():
|
|
75
|
-
if recursive:
|
|
76
|
-
files = list(path.rglob('*.ts')) + list(path.rglob('*.js')) + \
|
|
77
|
-
list(path.rglob('*.py')) + list(path.rglob('*.sol'))
|
|
78
|
-
else:
|
|
79
|
-
files = list(path.glob('*.ts')) + list(path.glob('*.js')) + \
|
|
80
|
-
list(path.glob('*.py')) + list(path.glob('*.sol'))
|
|
81
|
-
else:
|
|
82
|
-
click.echo(f"❌ Invalid path: {path}", err=True)
|
|
83
|
-
error_count += 1
|
|
84
|
-
continue
|
|
85
|
-
|
|
86
|
-
for file_path in files:
|
|
87
|
-
try:
|
|
88
|
-
# Read file
|
|
89
|
-
content = file_path.read_text()
|
|
90
|
-
|
|
91
|
-
# Convert
|
|
92
|
-
if target_format == 'lite':
|
|
93
|
-
converted = parser.standard_to_lite(content)
|
|
94
|
-
else:
|
|
95
|
-
converted = parser.lite_to_standard(content)
|
|
96
|
-
|
|
97
|
-
# Check if anything changed
|
|
98
|
-
if converted == content:
|
|
99
|
-
if verbose:
|
|
100
|
-
click.echo(f"⏭️ Skipped (no changes): {file_path}")
|
|
101
|
-
skipped_count += 1
|
|
102
|
-
continue
|
|
103
|
-
|
|
104
|
-
# Write or show
|
|
105
|
-
if dry_run:
|
|
106
|
-
click.echo(f"Would convert: {file_path}")
|
|
107
|
-
if verbose:
|
|
108
|
-
click.echo(f" {len(content)} → {len(converted)} chars")
|
|
109
|
-
else:
|
|
110
|
-
file_path.write_text(converted)
|
|
111
|
-
click.echo(f"✅ Converted: {file_path}")
|
|
112
|
-
|
|
113
|
-
converted_count += 1
|
|
114
|
-
|
|
115
|
-
except Exception as e:
|
|
116
|
-
click.echo(f"❌ Error converting {file_path}: {e}", err=True)
|
|
117
|
-
error_count += 1
|
|
118
|
-
|
|
119
|
-
# Summary
|
|
120
|
-
click.echo()
|
|
121
|
-
click.echo(f"Summary:")
|
|
122
|
-
click.echo(f" ✅ Converted: {converted_count}")
|
|
123
|
-
click.echo(f" ⏭️ Skipped: {skipped_count}")
|
|
124
|
-
if error_count > 0:
|
|
125
|
-
click.echo(f" ❌ Errors: {error_count}")
|
|
126
|
-
|
|
127
|
-
if dry_run:
|
|
128
|
-
click.echo()
|
|
129
|
-
click.echo("(Dry run - no files were modified)")
|
|
130
|
-
|
|
131
|
-
sys.exit(0 if error_count == 0 else 1)
|
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
VooDocs Lite - Abbreviation Dictionary
|
|
3
|
-
|
|
4
|
-
Provides bidirectional mapping between full words and abbreviations
|
|
5
|
-
for ultra-compact symbolic notation.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
# Abbreviation dictionary: abbr -> full
|
|
9
|
-
ABBREVIATIONS = {
|
|
10
|
-
# Storage & Data
|
|
11
|
-
'db': 'database',
|
|
12
|
-
'cfg': 'configuration',
|
|
13
|
-
'var': 'variable',
|
|
14
|
-
'const': 'constant',
|
|
15
|
-
'param': 'parameter',
|
|
16
|
-
'arg': 'argument',
|
|
17
|
-
'id': 'identifier',
|
|
18
|
-
|
|
19
|
-
# Common verbs
|
|
20
|
-
'must': 'must',
|
|
21
|
-
'be': 'be',
|
|
22
|
-
'is': 'is',
|
|
23
|
-
'are': 'are',
|
|
24
|
-
'has': 'has',
|
|
25
|
-
'have': 'have',
|
|
26
|
-
'does': 'does',
|
|
27
|
-
'do': 'do',
|
|
28
|
-
'will': 'will',
|
|
29
|
-
'can': 'can',
|
|
30
|
-
'should': 'should',
|
|
31
|
-
'may': 'may',
|
|
32
|
-
'contains': 'contains',
|
|
33
|
-
'returns': 'returns',
|
|
34
|
-
'expire': 'expire',
|
|
35
|
-
'expires': 'expires',
|
|
36
|
-
'stored': 'stored',
|
|
37
|
-
'signed': 'signed',
|
|
38
|
-
'hashed': 'hashed',
|
|
39
|
-
'valid': 'valid',
|
|
40
|
-
'logged': 'logged',
|
|
41
|
-
|
|
42
|
-
# Actions
|
|
43
|
-
'init': 'initialize',
|
|
44
|
-
'val': 'validate',
|
|
45
|
-
'ver': 'verify',
|
|
46
|
-
'gen': 'generate',
|
|
47
|
-
'cr': 'create',
|
|
48
|
-
'upd': 'update',
|
|
49
|
-
'del': 'delete',
|
|
50
|
-
'mod': 'modify',
|
|
51
|
-
'get': 'retrieve',
|
|
52
|
-
'qry': 'query',
|
|
53
|
-
'chk': 'check',
|
|
54
|
-
|
|
55
|
-
# Security
|
|
56
|
-
'auth': 'authentication',
|
|
57
|
-
'authz': 'authorization',
|
|
58
|
-
'pwd': 'password',
|
|
59
|
-
'tok': 'token',
|
|
60
|
-
|
|
61
|
-
# Entities
|
|
62
|
-
'usr': 'user',
|
|
63
|
-
'usrs': 'users',
|
|
64
|
-
|
|
65
|
-
# Time
|
|
66
|
-
'ts': 'timestamp',
|
|
67
|
-
'exp': 'expiration',
|
|
68
|
-
|
|
69
|
-
# Communication
|
|
70
|
-
'resp': 'response',
|
|
71
|
-
'req': 'request',
|
|
72
|
-
'msg': 'message',
|
|
73
|
-
|
|
74
|
-
# Status & Errors
|
|
75
|
-
'err': 'error',
|
|
76
|
-
'exc': 'exception',
|
|
77
|
-
'ok': 'success',
|
|
78
|
-
'fail': 'failure',
|
|
79
|
-
|
|
80
|
-
# Boolean & Values
|
|
81
|
-
'T': 'true',
|
|
82
|
-
'F': 'false',
|
|
83
|
-
'N': 'null',
|
|
84
|
-
'U': 'undefined',
|
|
85
|
-
'E': 'empty',
|
|
86
|
-
|
|
87
|
-
# Types
|
|
88
|
-
'str': 'string',
|
|
89
|
-
'num': 'number',
|
|
90
|
-
'int': 'integer',
|
|
91
|
-
'bool': 'boolean',
|
|
92
|
-
'arr': 'array',
|
|
93
|
-
'obj': 'object',
|
|
94
|
-
'fn': 'function',
|
|
95
|
-
|
|
96
|
-
# Blockchain
|
|
97
|
-
'addr': 'address',
|
|
98
|
-
'ctr': 'contract',
|
|
99
|
-
'tx': 'transaction',
|
|
100
|
-
'blk': 'block',
|
|
101
|
-
'bal': 'balance',
|
|
102
|
-
'amt': 'amount',
|
|
103
|
-
|
|
104
|
-
# Domain-specific
|
|
105
|
-
'sub': 'subdomain',
|
|
106
|
-
'subs': 'subdomains',
|
|
107
|
-
'reg': 'registry',
|
|
108
|
-
'own': 'owner',
|
|
109
|
-
'mgmt': 'management',
|
|
110
|
-
|
|
111
|
-
# Common words
|
|
112
|
-
'w/': 'with',
|
|
113
|
-
'wo/': 'without',
|
|
114
|
-
'svc': 'service',
|
|
115
|
-
'sys': 'system',
|
|
116
|
-
'ops': 'operations',
|
|
117
|
-
'ret': 'returns',
|
|
118
|
-
'res': 'result',
|
|
119
|
-
'val': 'value',
|
|
120
|
-
'vals': 'values',
|
|
121
|
-
'len': 'length',
|
|
122
|
-
'cnt': 'count',
|
|
123
|
-
'max': 'maximum',
|
|
124
|
-
'min': 'minimum',
|
|
125
|
-
'avg': 'average',
|
|
126
|
-
'sum': 'summary',
|
|
127
|
-
'desc': 'description',
|
|
128
|
-
'info': 'information',
|
|
129
|
-
'spec': 'specification',
|
|
130
|
-
'impl': 'implementation',
|
|
131
|
-
'ref': 'reference',
|
|
132
|
-
'def': 'definition',
|
|
133
|
-
'decl': 'declaration',
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
# Reverse mapping: full -> abbr
|
|
137
|
-
EXPANSIONS = {v: k for k, v in ABBREVIATIONS.items()}
|
|
138
|
-
|
|
139
|
-
# Symbol mappings
|
|
140
|
-
LITE_TO_STANDARD = {
|
|
141
|
-
'>': '⊢', # Purpose/Postcondition (context-dependent)
|
|
142
|
-
'@': '∂', # Dependencies
|
|
143
|
-
'!': '⚠', # Assumptions
|
|
144
|
-
'<': '⊳', # Preconditions
|
|
145
|
-
'=': '⊨', # Invariants
|
|
146
|
-
'~': '⚡', # Complexity
|
|
147
|
-
'#': '🔒', # Security
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
STANDARD_TO_LITE = {v: k for k, v in LITE_TO_STANDARD.items()}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
def expand_abbreviation(abbr: str) -> str:
|
|
154
|
-
"""Expand an abbreviation to its full form."""
|
|
155
|
-
return ABBREVIATIONS.get(abbr, abbr)
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
def compress_word(word: str) -> str:
|
|
159
|
-
"""Compress a word to its abbreviation."""
|
|
160
|
-
return EXPANSIONS.get(word.lower(), word)
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
def expand_text(text: str) -> str:
|
|
164
|
-
"""
|
|
165
|
-
Expand abbreviated text to full form.
|
|
166
|
-
|
|
167
|
-
Example:
|
|
168
|
-
"usr auth svc w/ JWT gen" -> "user authentication service with JWT generation"
|
|
169
|
-
"""
|
|
170
|
-
words = text.split()
|
|
171
|
-
expanded = []
|
|
172
|
-
|
|
173
|
-
for word in words:
|
|
174
|
-
# Check if word has punctuation
|
|
175
|
-
if word[-1] in '.,;:!?':
|
|
176
|
-
punct = word[-1]
|
|
177
|
-
word_part = word[:-1]
|
|
178
|
-
expanded_word = expand_abbreviation(word_part)
|
|
179
|
-
expanded.append(expanded_word + punct)
|
|
180
|
-
else:
|
|
181
|
-
expanded.append(expand_abbreviation(word))
|
|
182
|
-
|
|
183
|
-
return ' '.join(expanded)
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
def compress_text(text: str) -> str:
|
|
187
|
-
"""
|
|
188
|
-
Compress text using abbreviations.
|
|
189
|
-
|
|
190
|
-
Example:
|
|
191
|
-
"user authentication service with JWT generation" -> "usr auth svc w/ JWT gen"
|
|
192
|
-
"""
|
|
193
|
-
words = text.split()
|
|
194
|
-
compressed = []
|
|
195
|
-
|
|
196
|
-
for word in words:
|
|
197
|
-
# Check if word has punctuation
|
|
198
|
-
if word[-1] in '.,;:!?':
|
|
199
|
-
punct = word[-1]
|
|
200
|
-
word_part = word[:-1]
|
|
201
|
-
compressed_word = compress_word(word_part)
|
|
202
|
-
compressed.append(compressed_word + punct)
|
|
203
|
-
else:
|
|
204
|
-
compressed.append(compress_word(word))
|
|
205
|
-
|
|
206
|
-
return ' '.join(compressed)
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
def get_lite_symbol(standard_symbol: str) -> str:
|
|
210
|
-
"""Convert standard VooDocs symbol to Lite symbol."""
|
|
211
|
-
return STANDARD_TO_LITE.get(standard_symbol, standard_symbol)
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
def get_standard_symbol(lite_symbol: str) -> str:
|
|
215
|
-
"""Convert Lite symbol to standard VooDocs symbol."""
|
|
216
|
-
return LITE_TO_STANDARD.get(lite_symbol, lite_symbol)
|