diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml deleted file mode 100644 index c73e032..0000000 --- a/.github/workflows/pylint.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Pylint - -on: [push] - -jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: ["3.8", "3.9", "3.10"] - steps: - - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install pylint - - name: Analysing the code with pylint - run: | - pylint $(git ls-files '*.py') diff --git a/.gitignore b/.gitignore index 68bc17f..44bbb13 100644 --- a/.gitignore +++ b/.gitignore @@ -157,4 +157,5 @@ cython_debug/ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ +.idea/ +.vscode/ diff --git a/Readme.md b/Readme.md index 0519ecb..ff772e8 100644 --- a/Readme.md +++ b/Readme.md @@ -1 +1,19 @@ - \ No newline at end of file +1. Требуется установить Pandoc + +Pandoc - универсальный конвертер документов между различными форматами и разметками. + +2. Для того чтобы воспользоваться скриптом, скачайте репозиторий и введите команду: + +``` + pandoc --lua-filter=filter2.lua --from markdown --to docx --reference-doc=custom-reference3.docx < отчёт.md > отчёт.docx + ``` + + *Уточнение*. Установка Lua не требуется, так как интерпретатор этого языка программирования "зашит" внутрь Pandoc, хотя сам Pandoc написан на Haskell. + + Программа должна работать в Linux, macOS. По идее, она будет работать и в Windows, но важно сохранить файл .md в кодировке UTF-8. + + 3. Есть файл "правила оформления", он частично видоизменен, он неполный, там больший упор на то чего НЕ удалось реализовать в скрипте в автоматическом виде, но на что нужно обратить внимание (odg был создан в libreoffice draw, спокойно конвертируется в PDF). + +__ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ__. Программа является всего лишь ИНСТРУМЕНТОМ, и не заменяет голову на плечах, она предоставляется в том виде, в котором она была создана, она гарантированно многого все ещё *не* умеет (например, пока не придумал способ уместить в pandoc создание титульников) + +Часть первоначальной версии программы доступна в прошлых ревизиях Git и написана на Python. Текущая версия не требует установки Python в систему (и вообще никаких программ, кроме Pandoc), но была переписана на Lua, возможны регрессии функциональности. \ No newline at end of file diff --git a/filter.py b/filter.py index 8aa0bb4..15bbdbb 100755 --- a/filter.py +++ b/filter.py @@ -1,213 +1,82 @@ -#!/usr/bin/env python3 +# import json +# import sys +# import re -import json -import sys -import re +# body = json.loads(input()) +# blocks = body['blocks'] -sys.stdin.reconfigure(encoding='utf-8') # for windows +# def eprint(*args, **kwargs): +# print(*args, file=sys.stderr, **kwargs) -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 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 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 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 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': +# for token in mb_text_block['c'][::-1]: +# if token['t'] == 'Str': +# token['c'] = token['c'].rstrip('.?!…\t ') +# break -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 +# mb_text_block['c'] += [{'t' : 'Space'}] # a space after a paragraph and... +# + 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] +# #for i, b in enumerate(blocks): +# i = 0 +# image, formula, table, code, section = 0, 0, 0, 0, [0, 0, 0] +# E, W = "ОШИБКА: ", "ПРЕДУПРЕЖДЕНИЕ: " +# while i < len(blocks): +# b = blocks[i] +# btype = b['t'] - 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 == 'Table': +# if not append_reference(blocks[i-1], 'Таблица', section[0], table): +# eprint(E+"перед таблицей", b['c'],"нет абзаца, в который можно встроить ссылку на таблицу!") - 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)}) +# blocks[i+1] = {'t':'Div', 'c': [["",[],[['custom-style', 'aftertable']]], [blocks[i+1]]]} - for token in headerTokens: - if token['t'] == 'Str': - token['c'] = token['c'].upper() +# if btype == 'Figure': +# if not append_reference(blocks[i-1], 'Рисунок', section[0], image): +# eprint(E+"перед рисунком", b['c'], "нет абзаца, в который можно встроить ссылку на рисунок!") - if btype == 'Header' and order != 1: - if unnumbered: - eprint(E+ - "Используется заголовок 2 и ниже уровней", - b['c'][1], - "в ненумерованном разделе (или вовсе вне разделов). \ - Проверьте структуру разделов.") - sys.exit(1) +# if btype == 'CodeBlock': +# if len(b['c'][0][2]) == 0: +# eprint(E+"нет подписи у листинга:\n", b['c'][1], "\nЧТОБЫ ДОБАВИТЬ ПОДПИСЬ, используйте ключ caption:\n~~~{.lang caption=\"Hello world\"}") - upper_first_token(headerTokens) +# if not('caption' in dict(b['c'][0][2])): +# eprint(E+"нет подписи у листинга:\n", b['c'][1], "\nЧТОБЫ ДОБАВИТЬ ПОДПИСЬ, используйте ключ caption:\n~~~{.lang caption=\"Hello world\"}") - section_inc(order) - headerTokens.insert(0, {'t': 'Str', 'c': str(section_str(order)+HEADERSEP)}) +# 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'], "нет абзаца, в который можно встроить ссылку на листинг!") - if btype == 'Para': -# if unnumbered: -# eprint(E+"Текст или картинка вне раздела \ -# или в ненумерованном разделе", -# b['c'][1], -# ". Проверьте структуру разделов.") -# 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]]]} - 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}):') +# i += 1 - 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)) +# body['blocks'] = blocks +# print(json.dumps(body)) diff --git a/filter2.lua b/filter2.lua new file mode 100644 index 0000000..6a40b83 --- /dev/null +++ b/filter2.lua @@ -0,0 +1,267 @@ +IMAGE, FORMULA, TABLE, CODE = 0, 0, 0, 0 +UNNUMBERED = true +local hdlis = { + ['АННОТАЦИЯ'] = true, + ['ВВЕДЕНИЕ'] = true, + ['ЗАКЛЮЧЕНИЕ'] = true, + ['ВЫВОДЫ'] = true, + ['СПИСОК-ИСПОЛЬЗОВАННЫХ-ИСТОЧНИКОВ'] = true + } + + local section = {0, 0, 0} + + local function remove_trailing_punctuation(text) + return text:gsub("[,;%.!?]+$", "") + end + + local function capitalize_first_letter(text) + local first_char = pandoc.text.sub(text, 1, 1) + local rest = pandoc.text.sub(text, 2) + return pandoc.text.upper(first_char) .. rest + end + + local function is_unnumbered(header_text) + return hdlis[pandoc.text.upper(header_text)] ~= nil + end + + local function get_section_number(level) + if level == 1 then + section[1] = section[1] + 1 + section[2] = 0 + section[3] = 0 + IMAGE = 0 + + return tostring(section[1]) + elseif level == 2 then + if section[1] == 0 then + io.stderr:write("Ошибка: Второй уровень без первого запрещен\n") + return nil + end + section[2] = section[2] + 1 + section[3] = 0 + return section[1] .. "." .. section[2] + elseif level >= 3 then + if section[1] == 0 or section[2] == 0 then + io.stderr:write("Ошибка: Третий уровень без первого или второго запрещен\n") + return nil + end + section[3] = section[3] + 1 + return section[1] .. "." .. section[2] .. "." .. section[3] + end + end + + function Header(el) + local cleaned_text = capitalize_first_letter(remove_trailing_punctuation(pandoc.utils.stringify(el.content))) + local is_unnumbered_section = is_unnumbered(cleaned_text) + UNNUMBERED = is_unnumbered_section + local level = math.min(el.level, 3) -- Принудительно ограничиваем вложенность до 3 + + if level > 1 and section[1] == 0 then + io.stderr:write("Ошибка: Заголовки 2 и ниже без нумерованного заголовка 1 уровня\n") + return el + end + + if not is_unnumbered_section then + local section_number = get_section_number(level) + cleaned_text = section_number .. " " .. capitalize_first_letter(cleaned_text) + elseif level > 1 then + io.stderr:write("Ошибка: В ненумеруемом разделе не должно быть вложенных заголовков\n") + return el + end + + el.content = pandoc.Inlines(cleaned_text) + return el + end + + + +function Figure(el) + IMAGE = IMAGE + 1 + local str = pandoc.utils.stringify(el.caption) + str = capitalize_first_letter(str) + str = remove_trailing_punctuation(str) + if UNNUMBERED then + io.stderr:write("Ошибка: Рисунок " .. str .. " в ненумерованном разделе!") + return el + end + str = "Рисунок " .. section[1] .. "." .. IMAGE .. " — " .. str + + el.caption = pandoc.Blocks(str) + return el +end + +function Table(el) + TABLE = TABLE + 1 + local str = pandoc.utils.stringify(el.caption) + str = capitalize_first_letter(str) + str = remove_trailing_punctuation(str) + if UNNUMBERED then + io.stderr:write("Ошибка: Таблица " .. str .. " в ненумерованном разделе!") + return el + end + str = "Таблица " .. section[1] .. "." .. IMAGE .. " — " .. str + el.caption = pandoc.Blocks(str) + return el +end + +--[[ + Предполагается, что ранее в фильтре уже определены: + IMAGE, FORMULA, TABLE, CODE = 0, 0, 0, 0 + UNNUMBERED, hdlis, section + функции Header, Figure, Table (обрабатывающие подписи и прочее) + Этот блок добавляет модификацию соседних блоков (предыдущего Para для ссылки, + а также оборачивание следующего блока для Table и CodeBlock). +--]] + +-- Функция для приведения первой буквы строки к заглавной +function capitalize_first_letter(text) + local first = pandoc.text.sub(text, 1, 1) + local rest = pandoc.text.sub(text, 2) + return pandoc.text.upper(first) .. rest +end + +-- Функция оборачивает блок в Div с кастомным стилем "aftertable" +function wrap_aftertable(block) + return pandoc.Div(block, pandoc.Attr("", {}, {["custom-style"] = "aftertable"})) +end + +-- Функция, которая ищет в списке блоков блок по индексу index и, если это Para (или вложенный Para в Div), +-- удаляет завершающую пунктуацию у последнего текстового элемента и дописывает ссылку в виде: +-- " (Тип section.num):" +function append_reference_to_block(blocks, index, ref_name, section_num, num) + if index < 1 or index > #blocks then + return false + end + local blk = blocks[index] + -- Если блок – Div, пробуем взять последний вложенный блок из его содержимого + if blk.t == "Div" then + if blk.c and #blk.c >= 2 and type(blk.c[2]) == "table" and #blk.c[2] > 0 then + blk = blk.c[2][#blk.c[2]] + else + return false + end + end + if blk.t ~= "Para" then + return false + end + -- Удаляем завершающую пунктуацию у последнего Str + local inlines = blk.c + for j = #inlines, 1, -1 do + if inlines[j].t == "Str" then + inlines[j].text = inlines[j].text:gsub("[%.?!…%s]+$", "") + break + end + end + -- Формируем текст ссылки, например: "(Рисунок 1.2):" + local ref_text = "(" .. ref_name .. " " .. section_num .. "." .. num .. "):" + ref_text = capitalize_first_letter(ref_text) + table.insert(inlines, pandoc.Space()) + table.insert(inlines, pandoc.Str(ref_text)) + return true +end + +-- Главная функция фильтра, которая проходит по всем блокам документа и в нужных местах +-- модифицирует соседние блоки. +function Pandoc(doc) + local blocks = doc.blocks + local i = 1 + while i <= #blocks do + local blk = blocks[i] + if blk.t == "Table" then + -- Для таблиц: добавляем ссылку в предыдущий абзац и оборачиваем следующий блок + if not append_reference_to_block(blocks, i - 1, "Таблица", section[1], TABLE) then + io.stderr:write("ОШИБКА: перед таблицей нет абзаца для ссылки\n") + end + if i + 1 <= #blocks then + blocks[i + 1] = wrap_aftertable(blocks[i + 1]) + end + elseif blk.t == "Figure" then + -- Для рисунков: добавляем ссылку в предыдущий абзац + if not append_reference_to_block(blocks, i - 1, "Рисунок", section[1], IMAGE) then + io.stderr:write("ОШИБКА: перед рисунком нет абзаца для ссылки\n") + end + elseif blk.t == "CodeBlock" then + -- Для листингов: проверяем наличие подписи (caption) в атрибутах + local attr = blk.attr or {"", {}, {}} + local attributes = attr[3] or {} + local caption = attributes.caption + if not caption then + io.stderr:write("ОШИБКА: Листинг без подписи!\nИспользуйте ключ caption в CodeBlock\n") + else + CODE = CODE + 1 + local ref_text = "Листинг " .. section[1] .. "." .. CODE .. " — " .. caption + if not append_reference_to_block(blocks, i - 1, "Листинг", section[1], CODE) then + io.stderr:write("ОШИБКА: перед листингом нет абзаца для ссылки\n") + end + -- Вставляем блок с подписью перед текущим CodeBlock. + local caption_block = pandoc.Div( + pandoc.Para({ pandoc.Str(capitalize_first_letter(ref_text)) }), + pandoc.Attr("", {}, {["custom-style"] = "Code Caption"}) + ) + table.insert(blocks, i, caption_block) + i = i + 1 -- пропускаем вставленный блок + if i + 1 <= #blocks then + blocks[i + 1] = wrap_aftertable(blocks[i + 1]) + end + end + end + i = i + 1 + end + return pandoc.Pandoc(blocks, doc.meta) +end + +function Meta(m) + if m.date == nil then + m.date = os.date("%e «%m» %Y") + end + return m +end + +local function remove_trailing_punctuation_li (li) + return pandoc.Blocks(remove_trailing_punctuation(pandoc.utils.stringify(li))) +end + +local function add_trailing_semicolon_li (li) + return pandoc.Blocks(pandoc.utils.stringify(li) .. ";") +end + +local function add_trailing_stop_li (li) + return pandoc.Blocks(pandoc.utils.stringify(li) .. ".") +end + +local function capitalize_first_letter_li (li) + return pandoc.Blocks(capitalize_first_letter(pandoc.utils.stringify(li))) +end + +local function warnCapitalizedStart (li) + local str = pandoc.utils.stringify(li) + local capitalized = capitalize_first_letter(str) + if str == capitalized + then + io.stderr:write("Предупреждение: необходимо исправить вручную. В маркированном списке предложение должно начинаться со строчной (маленькой) буквы. Если текст пункта стартует с аббревиатуры, проигнорируйте данное предупреждение, иначе - исправьте вручную. Текст пункта:\n" .. str) + end + + return li +end + +function BulletList(el) + local li = el.content + li = pandoc.List.map(li, remove_trailing_punctuation_li) + li = pandoc.List.map(li, add_trailing_semicolon_li) + local ending = pandoc.List.at(el.content, -1) + pandoc.List.remove(li) + ending = add_trailing_stop_li(remove_trailing_punctuation_li(ending)) + pandoc.List.insert(li, ending) + li = pandoc.List.map(li, warnCapitalizedStart); + el.content = li + return el +end + +function OrderedList(el) + local li = el.content + li = pandoc.List.map(li, remove_trailing_punctuation_li) + li = pandoc.List.map(li, add_trailing_stop_li) + li = pandoc.List.map(li, capitalize_first_letter_li) + el.content = li + return el +end \ No newline at end of file diff --git a/отчёт.docx b/отчёт.docx new file mode 100644 index 0000000..19d1f3c Binary files /dev/null and b/отчёт.docx differ diff --git a/отчёт.md b/отчёт.md index c2d6dfb..7fb4366 100644 --- a/отчёт.md +++ b/отчёт.md @@ -2,21 +2,54 @@ title: Методика кодирования информации author: Студентов У.M. teacher: Беднов Г.А. +type: Курсовая --- -# введение +# введение. - + + Привет мир. -# Практическая работа -Здесь должен быть азбац с текстом -![Тебя что, в Гугле забанили](./google.png) +# практическая работа! +## очень маленький заголовок + + +## подраздельчик + +1. f +1. 2 +1. 2 +1. 4 + +* Ф; +* b, + +Здесь обязан быть абзац с текстом, так как он предваряет картинку + +![Тебя что, в Гугле забанили?](./google.png) Формулы оно тоже *может* поддерживать, но их обязательно надо доделывать! $$E=mc^2$$ +: пример таблички + + Right Left Center Default +------- ------ ---------- ------- + 12 12 12 12 + 123 123 123 123 + 1 1 1 1 + + +```cpp + +int main(void) { + std::cout << "Hello world"; + return 0; +} + +``` \ No newline at end of file