Tabel normal dalam penurunan harga


Tabel penurunan harga adalah neraka:


  1. Anda tidak dapat menulis teks dalam sel lebih dari beberapa kata, dan bahkan lebih sedikit daftar.
  2. Jika dialek memungkinkan paragraf 1, itu tidak nyaman untuk diformat.
  3. Jika sel tidak selaras, tabel tidak dapat dibaca.
  4. Tidak ada dukungan untuk tabel dengan tipe dan otomasi yang sama, seperti penomoran baris.

Sudah waktunya untuk menulis filter untuk Pandoc yang menggambar tabel dari YAML terstruktur, dengan penomoran baris, orientasi horizontal, pola grafik, dan pada saat yang sama mencari cara untuk menulis filter Lua.


Saya biasanya menulis teks dalam penurunan harga dan mengkonversi ke format target menggunakan Pandoc. Ini adalah program yang mengkonversi dokumen antara format, misalnya, dari Markdown Anda bisa mendapatkan HTML, dan dialek MD lainnya, dan DOCX, dan PDF (lebih dari 30 input dan lebih dari 50 format output). Pandoc Markdown memiliki banyak ekstensi yang nyaman untuk tautan, catatan kaki, tanda tangan, formula.


Pandoc berfungsi sebagai komposisi fungsi (akan ditulis dalam Haskell): format input spesifik β†’ representasi abstrak dokumen β†’ format output spesifik. Representasi abstrak dapat dimodifikasi menggunakan filter yang ditulis dalam Lua. Filter tidak perlu tahu tentang format output, tetapi mereka dapat memperhitungkannya.


Filter kami akan mencari blok abstrak kode dalam table bahasa bersyarat dalam representasi abstrak, baca YAML di dalamnya dan menghasilkan representasi abstrak tabel yang Pandoc sendiri akan hasilkan dalam format target.


 pandoc --lua-filter table.lua input.md -o output.html 

Apa saja alternatifnya dan mengapa lebih buruk?


  • Tabel HTML hanya berfungsi dalam penurunan harga dan dikonversi hanya menjadi HTML; hanya masalah pemformatan kaya dalam sel yang dipecahkan.
  • Generator tabel memerlukan pengalihan dari editor teks, sehingga tidak nyaman untuk mengedit konten sel di dalamnya ( contoh ).
  • Plugin editor ( Mode Org Emacs , plugin VIM ) tidak universal dan tidak selalu tersedia.

Sebaliknya, pandoc-crossref dan semua roti Pandoc bekerja dengan filter untuk tabel ringkasan. Filter juga dapat digunakan untuk menghasilkan tabel Penurunan harga standar dengan menentukan format output yang sesuai. Kerugiannya:


  • Sel tidak dapat digabungkan; Pandoc belum mendukung ini (belum).
  • Untuk tabel horizontal, gaya harus dilakukan menggunakan format output, misalnya, melalui CSS.

Deskripsi tabel mencakup tiga bagian:


  1. Struktur meja


    Daftar grafik (kolom) yang diurutkan:


    • Minimal, kolom harus memiliki judul.
    • Agar dapat mengatur ulang kolom tanpa menyentuh data, atribut rekaman yang ditampilkan di kolom ( id ) harus ditentukan.
    • Kolom khusus tidak memiliki id, tetapi memiliki deskripsi tentang cara mengisinya. Pertama, Anda memerlukan nomor seri ( special: number ).
    • Penjajaran kolom ( align ).

    Juga, tabel bisa vertikal atau horizontal ( orientation ). Dalam kasus terakhir, grafiknya adalah baris.


  2. Properti tabel: ID untuk tautan ( id ) dan tanda tangan ( caption ). Pandoc memungkinkan Anda untuk menandatangani tabel, tetapi bukan blok kode.


  3. Data dalam bentuk array kamus YAML.



Strukturnya bisa umum untuk beberapa tabel, sehingga Anda bisa menggambarkannya secara langsung dengan tabel, dan sekali dalam metadata (hal-depan), dan kemudian merujuk ke templat bernama.


Rencana Implementasi:


  1. Dari metadata dokumen kami membentuk kamus templat.


  2. Untuk setiap blok kode dengan table kelas:


    1. Kami mem-parsing tabel YAML.
    2. Jika templat ditentukan, kami ambil dari kamus, kalau tidak kami isi templat dari YAML.
    3. Kami mengisi properti individual tabel dari YAML.
    4. Kami membentuk entri tabel dari YAML (catatan adalah baris dalam tabel biasa atau kolom dalam yang horizontal).
    5. Kami "menggambar" tabel sesuai dengan templat, properti, dan catatan.


Level atas diimplementasikan sebagai tertulis (semua kode tersedia di tautan di akhir artikel):


 function Pandoc(doc) local meta_templates = doc.meta['table-templates'] if meta_templates then for name, value in pairs(meta_templates) do templates[name] = parse_template(value) end end local blocks = pandoc.walk_block(pandoc.Div(doc.blocks), { CodeBlock = create_table }) return pandoc.Pandoc(blocks, doc.meta) end 

Fungsi parse_template() sedikit mengubah format metadata. Pandoc mewakili nilainya sebagai objek MetaBlock dan MetaInline . Entah garis-garis sederhana dibuat pandoc.utils.stringify() (misalnya, orientasi), atau elemen visual (misalnya, blok teks dalam judul kolom).


Tentang debugging. Ada banyak contoh dalam dokumentasi Pandoc, tetapi tipenya tidak terlalu detail. Untuk filter debugging, lebih mudah untuk memiliki fungsi dump variabel. Perpustakaan serius mencetak terlalu banyak detail, saya lebih suka salah satu opsi sederhana.


Fungsi untuk mengubah metadata menjadi elemen dokumen
 local function to_inlines(content) if content == nil then return {} elseif type(content) == 'string' then return {pandoc.Str(content)} elseif type(content) == 'number' then return to_inlines(tostring(content)) elseif content.t == 'MetaInlines' then inlines = {} for i, item in ipairs(content) do inlines[i] = item end return inlines end end local function to_blocks(content) if (type(content) == 'table') and content.t == 'MetaBlocks' then return content else return {pandoc.Plain(to_inlines(content))} end end 

Fungsi create_table() dipanggil untuk setiap blok kode dalam triple backtics.


Kami hanya tertarik pada blok kode β€œdalam bahasa” table :


 if not contains('table', block.classes) then return block end 

Untuk mem-parse YAML di dalam blok kode, kami membuat dokumen yang hanya terdiri dari metadata YAML, parsing dengan Pandoc dan hanya menyisakan metadata:


 local meta = pandoc.read('---\n' .. block.text .. '\n---').meta 

Selanjutnya, dari meta tautan ke templat atau struktur tabel dan properti dari tabel tertentu dibaca.


Fungsi fill_table() membaca dari data meta pada atribut yang ditentukan dalam deskripsi grafik. Pada tahap yang sama, jika kolom ditandai sebagai spesial, isinya dihasilkan:


 local data = {} for i, serie in ipairs(template.series) do if serie.special == 'number' then data[i] = to_blocks(#datum + 1) else data[i] = to_blocks(item[serie.id]) end end 

Fungsi format_table() membentuk array sel yang dihasilkan tergantung pada orientasi tabel dan membuat objek tabel abstrak. Perlu dicatat bahwa jika lebar atau header harus ditetapkan untuk semua kolom atau tanpa kolom, jika tidak Pandoc tidak akan membuat tabel.


Skrip yang sudah selesai dapat diletakkan di ~/.local/share/pandoc ( direktori data ~/.local/share/pandoc ) untuk mengaksesnya dengan nama dari mana saja.


PS


Tentang akuntansi untuk filter format output. Misalnya, saya menulis spoiler di Pandoc seperti ini:


 ::: {.spoiler title=""}  . ::: 

Tidak ada spoiler dalam model dokumen Pandoc, jadi filter harus menghasilkan blok mentah kira-kira dengan cara berikut. Tentu saja, kode asli ( spoiler.lua ) harus mempertimbangkan format output melalui variabel FORMAT , dan tidak secara mekanis: fragmen di bawah ini menghasilkan blok mentah dalam HTML, meskipun format output adalah penurunan harga.


 function Div(el) if not el.attr or not contains('spoiler', el.attr.classes) then return el end local title = el.attr.attributes['title'] or '' table.insert(el.content, 1, pandoc.RawBlock('html', '<' .. 'spoiler title="' .. title .. '">', 'RawBlock')) table.insert(el.content, pandoc.RawBlock('html', '<' .. '/spoiler>', 'RawBlock')) return el.content end 

Referensi


Source: https://habr.com/ru/post/id474826/


All Articles