pyact-cli 0.7.1__tar.gz → 0.7.3__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyact-cli
3
- Version: 0.7.1
3
+ Version: 0.7.3
4
4
  Summary: A CLI tool to compile .pamd files to Markdown.
5
5
  Home-page: https://github.com/Abstergo2003/PyAct
6
6
  Author: Abstergo2003
@@ -21,6 +21,16 @@ def equation(func: Callable, values: List[Any]) -> str:
21
21
  value = func(*values)
22
22
  name, sep, tail = source.rpartition("=")
23
23
  head, sep, equ = tail.rpartition(":")
24
+
25
+ name = name.strip()
26
+ if "_" in name:
27
+ parts = name.split("_", 1)
28
+ name = f"{parts[0]}_{{{parts[1]}}}"
29
+
30
+ import re
31
+ greek_pattern = r'(?<![a-zA-Z])(alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega|Alpha|Beta|Gamma|Delta|Epsilon|Zeta|Eta|Theta|Iota|Kappa|Lambda|Mu|Nu|Xi|Omicron|Pi|Rho|Sigma|Tau|Upsilon|Phi|Chi|Psi|Omega)(?![a-zA-Z])'
32
+ name = re.sub(greek_pattern, r'\\\1', name)
33
+
24
34
  return f"$$ {name} = {py2tex(equ.replace(chr(10), ''))} = {value} $$"
25
35
 
26
36
  def image(link: str, caption: str) -> str:
@@ -82,11 +82,11 @@ def markdown_parser(md_text: str) -> list:
82
82
  blocks.append(('list', text, 'unordered'))
83
83
 
84
84
  elif re.match(r'^\d+\.\s+', line_s):
85
- m = re.match(r'^\d+\.\s+(.*)', line_s)
86
- blocks.append(('list', m.group(1), 'ordered'))
85
+ m = re.match(r'^(\d+)\.\s+(.*)', line_s)
86
+ blocks.append(('list', m.group(2), 'ordered', int(m.group(1))))
87
87
 
88
88
  # Math Block Parsing
89
- elif line_s.startswith('$$') and line_s.endswith('$$'):
89
+ elif (line_s.startswith('$$') and line_s.endswith('$$')) or (line_s.startswith('$') and line_s.endswith('$') and len(line_s) >= 2):
90
90
  blocks.append(('math', line_s.strip('$').strip()))
91
91
 
92
92
  # Standard Paragraph
@@ -312,15 +312,17 @@ def _add_image(paragraph, url, caption, styles):
312
312
  def _process_inline(paragraph, text, styles, tag):
313
313
  """Parses text for images, links, math, and bold/italic."""
314
314
  # Simple regex to split by math, image, or link. Captures the match as a group.
315
- # Group 5: Footnote definition [^1]: ...
316
- # Group 6: Footnote annotation [^1]
317
- pattern = r'(\$\$.*?\$\$)|(!\[.*?\]\(.*?\))|(\[.*?\]\(.*?\))|(<span.*?>.*?</span>)|(\[\^.*?\]:.*?$)|(\[\^.*?\])'
315
+ # Group 1: Double $$ math
316
+ # Group 2: Single $ math
317
+ # Group 6: Footnote definition [^1]: ...
318
+ # Group 7: Footnote annotation [^1]
319
+ pattern = r'(\$\$.*?\$\$)|(\$.*?\$)|(!\[.*?\]\(.*?\))|(\[.*?\]\(.*?\))|(<span.*?>.*?</span>)|(\[\^.*?\]:.*?$)|(\[\^.*?\])'
318
320
  parts = re.split(pattern, text)
319
321
 
320
322
  for part in parts:
321
323
  if not part: continue
322
324
 
323
- if part.startswith('$$') and part.endswith('$$'):
325
+ if (part.startswith('$$') and part.endswith('$$')) or (part.startswith('$') and part.endswith('$') and len(part) >= 2):
324
326
  math_text = part.strip('$').strip()
325
327
  try:
326
328
  math2docx.add_math(paragraph, math_text)
@@ -381,6 +383,48 @@ def _process_inline(paragraph, text, styles, tag):
381
383
  run = paragraph.add_run(subpart)
382
384
  if tag in styles: _apply_css_to_run(run, styles[tag])
383
385
 
386
+ def _restart_list_numbering(doc, p):
387
+ try:
388
+ num_part = doc.part.numbering_part
389
+ numbering = num_part.numbering_definitions._numbering
390
+ nums = numbering.xpath('w:num')
391
+ if not nums: return None
392
+ max_id = max([int(n.get(qn('w:numId'))) for n in nums])
393
+ new_id = max_id + 1
394
+
395
+ list_num = numbering.xpath('w:num[@w:numId="5"]')
396
+ if not list_num: list_num = nums
397
+ abstract_id = list_num[0].xpath('w:abstractNumId/@w:val')[0]
398
+
399
+ new_num = OxmlElement('w:num')
400
+ new_num.set(qn('w:numId'), str(new_id))
401
+ ab_num_id = OxmlElement('w:abstractNumId')
402
+ ab_num_id.set(qn('w:val'), abstract_id)
403
+ new_num.append(ab_num_id)
404
+
405
+ lvl_override = OxmlElement('w:lvlOverride')
406
+ lvl_override.set(qn('w:ilvl'), "0")
407
+ start_override = OxmlElement('w:startOverride')
408
+ start_override.set(qn('w:val'), "1")
409
+ lvl_override.append(start_override)
410
+ new_num.append(lvl_override)
411
+
412
+ numbering.append(new_num)
413
+
414
+ pPr = p._p.get_or_add_pPr()
415
+ numPr = OxmlElement('w:numPr')
416
+ ilvl = OxmlElement('w:ilvl')
417
+ ilvl.set(qn('w:val'), "0")
418
+ numId_el = OxmlElement('w:numId')
419
+ numId_el.set(qn('w:val'), str(new_id))
420
+ numPr.append(ilvl)
421
+ numPr.append(numId_el)
422
+ pPr.append(numPr)
423
+
424
+ return new_id
425
+ except Exception:
426
+ return None
427
+
384
428
  def docx_writer(blocks: list, styles: dict, output_file: str):
385
429
  """
386
430
  Translates parsed markdown blocks into a Word document and applies CSS styling.
@@ -399,6 +443,7 @@ def docx_writer(blocks: list, styles: dict, output_file: str):
399
443
  None: This function does not return a value, but it writes a binary .docx file to disk.
400
444
  """
401
445
  doc = Document()
446
+ current_ordered_numId = None
402
447
 
403
448
  # Global body style
404
449
  if 'body' in styles:
@@ -426,8 +471,27 @@ def docx_writer(blocks: list, styles: dict, output_file: str):
426
471
  elif btype == 'list':
427
472
  text = block[1]
428
473
  list_type = block[2] if len(block) > 2 else 'unordered'
474
+ num_val = block[3] if len(block) > 3 else None
475
+
429
476
  style = 'List Number' if list_type == 'ordered' else 'List Bullet'
430
477
  p = doc.add_paragraph(style=style)
478
+
479
+ if list_type == 'ordered':
480
+ if num_val == 1:
481
+ new_id = _restart_list_numbering(doc, p)
482
+ if new_id:
483
+ current_ordered_numId = new_id
484
+ elif current_ordered_numId:
485
+ pPr = p._p.get_or_add_pPr()
486
+ numPr = OxmlElement('w:numPr')
487
+ ilvl = OxmlElement('w:ilvl')
488
+ ilvl.set(qn('w:val'), "0")
489
+ numId_el = OxmlElement('w:numId')
490
+ numId_el.set(qn('w:val'), str(current_ordered_numId))
491
+ numPr.append(ilvl)
492
+ numPr.append(numId_el)
493
+ pPr.append(numPr)
494
+
431
495
  if 'list' in styles:
432
496
  _apply_paragraph_formatting(p, styles['list'])
433
497
  _process_inline(p, text, styles, 'list')
@@ -17,7 +17,24 @@ class LatexVisitor(ast.NodeVisitor):
17
17
  return 1000
18
18
 
19
19
  def visit_Name(self, n):
20
- return n.id
20
+ name = n.id
21
+ if "_" in name:
22
+ parts = name.split('_', 1)
23
+ name = f"{parts[0]}_{{{parts[1]}}}"
24
+
25
+ greek_letters = [
26
+ 'alpha', 'beta', 'gamma', 'delta', 'epsilon', 'zeta', 'eta', 'theta', 'iota',
27
+ 'kappa', 'lambda', 'mu', 'nu', 'xi', 'omicron', 'pi', 'rho', 'sigma', 'tau',
28
+ 'upsilon', 'phi', 'chi', 'psi', 'omega',
29
+ 'Alpha', 'Beta', 'Gamma', 'Delta', 'Epsilon', 'Zeta', 'Eta', 'Theta', 'Iota',
30
+ 'Kappa', 'Lambda', 'Mu', 'Nu', 'Xi', 'Omicron', 'Pi', 'Rho', 'Sigma', 'Tau',
31
+ 'Upsilon', 'Phi', 'Chi', 'Psi', 'Omega'
32
+ ]
33
+ import re
34
+ greek_pattern = r'(?<![a-zA-Z])(' + '|'.join(greek_letters) + r')(?![a-zA-Z])'
35
+ name = re.sub(greek_pattern, r'\\\1', name)
36
+
37
+ return name
21
38
 
22
39
  def prec_Name(self, n):
23
40
  return 1000
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyact-cli
3
- Version: 0.7.1
3
+ Version: 0.7.3
4
4
  Summary: A CLI tool to compile .pamd files to Markdown.
5
5
  Home-page: https://github.com/Abstergo2003/PyAct
6
6
  Author: Abstergo2003
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
5
5
 
6
6
  setup(
7
7
  name="pyact-cli",
8
- version="0.7.1",
8
+ version="0.7.3",
9
9
  author="Abstergo2003",
10
10
  author_email="",
11
11
  description="A CLI tool to compile .pamd files to Markdown.",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes