feat: подсветка синтаксиса CFML в docx, относительные пути
This commit is contained in:
+71
-8
@@ -7,9 +7,16 @@
|
||||
3. Строит DOCX:
|
||||
- Титульная страница (название, подзаголовок, дата)
|
||||
- Оглавление (поле Word TOC — пользователь жмёт правую кнопку → Обновить поле)
|
||||
- 47 разделов с кодом (заголовок файла + код моноширинным шрифтом на сером фоне)
|
||||
- разделы с кодом (заголовок файла + код с подсветкой синтаксиса на сером фоне)
|
||||
- Номер страницы в нижнем колонтитуле
|
||||
|
||||
Подсветка синтаксиса CFML (4 цвета):
|
||||
синий — CF-теги (<cfif>, <cfset>, </cffunction>, ...)
|
||||
зелёный — строковые значения ("...", '...')
|
||||
фиолетовый — выражения в # (#variables#, #func()#)
|
||||
тёмно-голубой — SQL-ключевые слова (SELECT, FROM, WHERE, JOIN, ...)
|
||||
чёрный — всё остальное
|
||||
|
||||
Запуск:
|
||||
/home/naeel/svc-api-x/.venv/bin/python build_docx.py
|
||||
|
||||
@@ -39,8 +46,8 @@ from docx.enum.text import WD_ALIGN_PARAGRAPH
|
||||
from docx.oxml.ns import qn
|
||||
from docx.oxml import OxmlElement
|
||||
|
||||
BUNDLE_PATH = '/home/naeel/svc-api-x/results/source-bundle.md' # входной файл
|
||||
OUTPUT_PATH = '/home/naeel/svc-api-x/results/svc-api-x.docx' # выходной файл
|
||||
BUNDLE_PATH = 'results/source-bundle.md' # входной файл
|
||||
OUTPUT_PATH = 'results/svc-api-x.docx' # выходной файл
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -70,7 +77,61 @@ def parse_bundle(path):
|
||||
# Вспомогательные функции
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def set_font(run, name='Courier New', size=9, bold=False, color=None):
|
||||
# ---------------------------------------------------------------------------
|
||||
# Токенизатор CFML
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Цвета подсветки (RGB)
|
||||
COL_TAG = (0x1A, 0x5F, 0xB4) # синий — CF-теги
|
||||
COL_STR = (0x1E, 0x7E, 0x34) # зелёный — строки
|
||||
COL_VAR = (0x6F, 0x31, 0x78) # фиолетовый — #переменные#
|
||||
COL_SQL = (0x0D, 0x5C, 0x73) # тёмно-голубой — SQL
|
||||
COL_DEF = None # чёрный (default)
|
||||
|
||||
_PATTERNS = [
|
||||
('tag', re.compile(
|
||||
r'</cf\w+|<cf\w+|</cfscript>|<cfscript>', re.IGNORECASE)),
|
||||
('var', re.compile(
|
||||
r'#[^#\n]+#')),
|
||||
('str', re.compile(
|
||||
r'"[^"\n]*"|' + r"'[^'\n]*'")),
|
||||
('sql', re.compile(
|
||||
r'\b(SELECT|FROM|WHERE|JOIN|LEFT|RIGHT|INNER|OUTER|ON|AND|OR|NOT|'
|
||||
r'INSERT|INTO|UPDATE|DELETE|SET|GROUP|ORDER|BY|HAVING|LIMIT|OFFSET|'
|
||||
r'AS|DISTINCT|COUNT|SUM|AVG|MAX|MIN|CAST|COALESCE|CASE|WHEN|THEN|'
|
||||
r'ELSE|END|IS|NULL|IN|EXISTS|UNION|ALL)\b', re.IGNORECASE)),
|
||||
]
|
||||
|
||||
_COLOR_MAP = {'tag': COL_TAG, 'str': COL_STR, 'var': COL_VAR,
|
||||
'sql': COL_SQL, None: COL_DEF}
|
||||
|
||||
|
||||
def tokenize_cfml(line):
|
||||
"""Разбивает строку кода на список (text, color) с подсветкой CFML."""
|
||||
tokens = []
|
||||
pos = 0
|
||||
length = len(line)
|
||||
while pos < length:
|
||||
best_match = None
|
||||
best_kind = None
|
||||
best_start = length
|
||||
for kind, pat in _PATTERNS:
|
||||
m = pat.search(line, pos)
|
||||
if m and m.start() < best_start:
|
||||
best_match = m
|
||||
best_kind = kind
|
||||
best_start = m.start()
|
||||
if best_match is None:
|
||||
tokens.append((line[pos:], COL_DEF))
|
||||
break
|
||||
if best_start > pos:
|
||||
tokens.append((line[pos:best_start], COL_DEF))
|
||||
tokens.append((best_match.group(0), _COLOR_MAP[best_kind]))
|
||||
pos = best_match.end()
|
||||
return tokens
|
||||
|
||||
|
||||
def set_font(run, name='Courier New', size=8, bold=False, color=None):
|
||||
run.font.name = name
|
||||
run.font.size = Pt(size)
|
||||
run.font.bold = bold
|
||||
@@ -259,11 +320,13 @@ def build(sections):
|
||||
|
||||
for idx, line in enumerate(lines):
|
||||
if idx > 0:
|
||||
run = code_para.add_run()
|
||||
br_run = code_para.add_run()
|
||||
br = OxmlElement('w:br')
|
||||
run._r.append(br)
|
||||
run = code_para.add_run(line)
|
||||
set_font(run, name='Courier New', size=8)
|
||||
br_run._r.append(br)
|
||||
set_font(br_run)
|
||||
for text, color in tokenize_cfml(line):
|
||||
run = code_para.add_run(text)
|
||||
set_font(run, color=color)
|
||||
|
||||
doc.save(OUTPUT_PATH)
|
||||
print(f'Готово: {OUTPUT_PATH}')
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user