#!/usr/bin/env python3 import json import sys import re sys.stdin.reconfigure(encoding='utf-8') # for windows image, formula, table, code, section = 0, 0, 0, 0, [0, 0, 0] E, W = "ОШИБКА: ", "ПРЕДУПРЕЖДЕНИЕ: " SP = [{'t' : 'Space'}] unnumbered = True HEADERSEP = ' ' hdlis = [ 'АННОТАЦИЯ', 'ВВЕДЕНИЕ', 'ЗАКЛЮЧЕНИЕ', 'ВЫВОДЫ', 'СПИСОК-ИСПОЛЬЗОВАННЫХ-ИСТОЧНИКОВ' ] body = json.loads(input()) blocks = body['blocks'] def eprint(*args, **kwargs): print(*args, file=sys.stderr, **kwargs) def str2pd(str_to_pandoc): def intersperse(lst, item): result = [item] * (len(lst) * 2 - 1) result[0::2] = lst return result return intersperse(list(map( lambda x: {'t': 'Str', 'c': x}, list(filter(lambda x: x != '', re.split('[\t\n\r ]', str_to_pandoc))))), {'t': 'Space'}) def section_inc (index): if index <= 1: global image, formula, table, code image, formula, table, code = 0, 0, 0, 0 global section section[index-1] += 1 section[index:] = [0]*len(section[index:]) def section_str (index): return str(section[0]) if index <= 1 else section_str(index-1)+"."+str(section[index-1]) def phrase_list (phrase, listtype, islast): if listtype == 'OrderedList': inl, start = 'в нумерованном списке ', 'большой (заглавной) ' else: inl, start = 'в маркированном списке ', 'маленькой (строчной) ' endswith = "пункт заканчивается знаком " ender, subender = '.', ';' if not islast and listtype != 'OrderedList': ender, subender = subender, ender if phrase[0]['t'] == 'Plain': if phrase[0]['c'][0]['c'][0].islower() and (listtype == 'OrderedList'): phrase[0]['c'][0]['c'] = phrase[0]['c'][0]['c'][0].upper() + phrase[0]['c'][0]['c'][1:] if phrase[0]['c'][0]['c'][0].isupper() != (listtype == 'OrderedList'): eprint(W+inl+'текст должен начинаться с ' + start + 'буквы') if phrase[0]['c'][-1]['c'][-1] == subender: if islast: eprint(W + inl + "последний " + endswith + ender, ", хотя остальных пунктах используется ", subender) else: eprint(W+inl+"каждый" + endswith + ender, " , а не знаком ", subender) elif phrase[0]['c'][-1]['c'][-1] != ender: phrase[0]['c'][-1]['c'] += ender return phrase def text_ref (prev, caption, section, figure): return str2pd(f'{caption} {section}.{figure} —') + SP + prev def delete_end_marks (tokens, chars='.?!…\t '): for token in tokens[::-1]: if token['t'] == 'Str': token['c'] = token['c'].rstrip(chars) break return tokens def upper_first_token(tokens): for token in tokens: if token['t'] == 'Str': token['c'] = token['c'][0].upper() + token['c'][1:] break return tokens def append_reference (mb_text_block, name, section0, num): if mb_text_block['t'] == 'Div': mb_text_block = mb_text_block['c'][-1][0] if mb_text_block['t'] == 'Para': delete_end_marks(mb_text_block['c']) mb_text_block['c'] += SP + upper_first_token(str2pd(f'({name} {section0}.{num}):')) return True return False #for i, b in enumerate(blocks): i = 0 while i < len(blocks): b = blocks[i] btype = b['t'] if btype == 'Header': order = b['c'][0] refname = b['c'][1][0] headerTokens = b['c'][2] delete_end_marks(headerTokens) if btype == 'Header' and order == 1: unnumbered = (refname.strip()).upper() in hdlis if not unnumbered: section_inc(order) headerTokens.insert(0, {'t': 'Str', 'c': str(section_str(order)+HEADERSEP)}) for token in headerTokens: if token['t'] == 'Str': token['c'] = token['c'].upper() if btype == 'Header' and order != 1: if unnumbered: eprint(E+ "Используется заголовок 2 и ниже уровней", b['c'][1], "в ненумерованном разделе (или вовсе вне разделов). \ Проверьте структуру разделов.") sys.exit(1) upper_first_token(headerTokens) section_inc(order) headerTokens.insert(0, {'t': 'Str', 'c': str(section_str(order)+HEADERSEP)}) if btype == 'Para': # if unnumbered: # eprint(E+"Текст или картинка вне раздела \ # или в ненумерованном разделе", # b['c'][1], # ". Проверьте структуру разделов.") # sys.exit(1) for bb in b['c']: bbtype = bb['t'] if bbtype == 'Image': image += 1 b['c'][0]['c'][1] = text_ref(b['c'][0]['c'][1], 'Рисунок', section[0], image) # TODO error if fail delete_end_marks(blocks[i-1]['c']) blocks[i-1]['c'] += SP + str2pd(f'(Рисунок {section[0]}.{image}):') if btype == 'Table': if unnumbered: eprint(E+"Таблица вне раздела или в ненумерованном разделе:\n", b['c'], "\nПровертье структуру разделов.") sys.exit(1) table += 1 b['c'][1][1][0]['c'] = str2pd(f'Таблица {section[0]}.{table} —') + SP + b['c'][1][1][0]['c'] if not append_reference(blocks[i-1], 'Таблица', section[0], table): eprint(E+"перед таблицей", b['c'],"нет абзаца, в который можно встроить ссылку на таблицу!") sys.exit(1) blocks[i+1] = {'t':'Div', 'c': [["",[],[['custom-style', 'aftertable']]], [blocks[i+1]]]} if btype == 'Figure': if unnumbered: eprint(E+"Рисунок вне раздела или в ненумерованном разделе:\n", b['c'], "\nПровертье структуру разделов.") sys.exit(1) image += 1 b['c'][1][1][0]['c'] = str2pd(f'Рисунок {section[0]}.{image} —') + SP + b['c'][1][1][0]['c'] if not append_reference(blocks[i-1], 'Рисунок', section[0], image): eprint(E+"перед рисунком", b['c'], "нет абзаца, в который можно встроить ссылку на рисунок!") sys.exit(1) if btype == 'CodeBlock': if unnumbered: eprint(E+"Листинг вне раздела или в ненумерованном разделе:\n", b['c'], "\nПровертье структуру разделов.") sys.exit(1) if len(b['c'][0][2]) == 0: eprint(E+"нет подписи у листинга:\n", b['c'][1], "\nЧТОБЫ ДОБАВИТЬ ПОДПИСЬ, используйте ключ caption:\n~~~{.lang caption=\"Hello world\"}") sys.exit(1) if not('caption' in dict(b['c'][0][2])): eprint(E+"нет подписи у листинга:\n", b['c'][1], "\nЧТОБЫ ДОБАВИТЬ ПОДПИСЬ, используйте ключ caption:\n~~~{.lang caption=\"Hello world\"}") sys.exit(1) code += 1 caption = f'Листинг {section[0]}.{code} — ' + dict(b['c'][0][2])['caption'] if not append_reference(blocks[i-1], 'Листинг', section[0], code): eprint(E+"перед листингом", b['c'], "нет абзаца, в который можно встроить ссылку на листинг!") sys.exit(1) blocks.insert(i, {"t":"Div","c":[["",[],[["custom-style","Code Caption"]]], [{"t":"Para","c":str2pd(caption)}]]}) i += 1 blocks[i+1] = {'t':'Div', 'c': [["",[],[['custom-style', 'aftertable']]], [blocks[i+1]]]} # eprint(blocks[i+1]) # .insert(i, {"t":"Div","c":[["",[],[["custom-style","Code Caption"]]], [{"t":"Para","c":str2pd(caption)}]]}) if btype == 'BulletList': for j, phrase in enumerate(b['c']): phrase = phrase_list(phrase, btype, j == (len(b['c']) - 1)) if btype == 'OrderedList': for phrase in b['c'][1]: phrase = phrase_list(phrase, btype, False) i += 1 body['blocks'] = blocks print(json.dumps(body))