pandoc-filter

لذت برنامه نویسی: نوشتن یک pandoc filter با python

اینم یه تجربه پراکنده دیگه!

همنطور که اخیرا زیاد نوشتم فرمت مورد علاقه تولید مستندات من markdown شده و برای تبدیل کردنش به یه متن تر و تمیز pdf از pandoc به همراه xepersian استفاده می‌کنم. حالا این وسط من یه مشکلی داشتم و اونم این بود که متون انگلیسی توی فارسی به درستی به فرمت xepersian تبدیل نمی‌شدند و هی مجبور بودم بصورت دستی متن latex بدست آمده رو ویرایش کنم. به همین خاطر علاقه مند شدم که ببینم چطور می‌شه این مشکل رو توی pandoc حل کرد. راه حل از این قراره که شما بایستی یه فیلتر برای pandoc تعریف کنی و اون pandoc filter اون کاری که ما دوست داریم رو برای ما انجام میده!

فیلترهای pandoc

زبان برنامه نویسی که pandoc با اون توسعه یافته haskell هست که خب به نظر من زبان عجیب غریبی هست. شما می‌تونید با استفاده از این زبان فیلترها رو توسعه بدید. کل ماجرای فیلترها هم از این قراره که ابتدا pandoc متن ورودی رو میخونه و به ساختار سلسله مراتبی داخلی خودش تبدیل می‌کنه. حالا این ساختار رو بصورت اصلی (که فقط در زبان haskell در دسترسه) یا بصورت json در اختیار فیلتر شما قرار می‌ده و فیلتر شما بر اساس فرمت نهایی، نوع المنت و متا دیتاهای مربوط به اون المنت تصمیم می‌گیره که چه کاری انجام بده. تقریبا هیچ مستندات درست حسابی من پیدا نکردم که همه چیز رو توضیح داده باشه، اما سعی کردم به کمک آزمایش و خطا و همچنین دیدن فیلترهای مشابهی که برای کارهای مختلف توسعه پیدا کرده بود گلیم خودم رو از آب بیرون بکشم.

همچنین میشه این فیلترها رو به زبانی غیر از haskell توسعه داد. این زبان‌های پایتون، جاوا اسکریپت(در محیط nodejs)، پرل و php هست. من به علت آشنایی بیشترم با پایتون از اون استفاده کردم

نحوه توسعه

کل روند از این قراره که شما فایل پایتون رو بصورت یک فیلتر با دسترسی اجرایی در اختیار pandoc قرار میدید و اون تابع main رو صدا میزنه. پس از اون اطلاعات از stdin به برنامه داده شده و خروجی‌ها از stdout گرفته می‌شه. خود توسعه دهنده pandoc هم پکیجی به نام pandocfilters توسعه داده که با استفاده از pip یا ابزارهای مشابه قابل نصب و استفاده است.

تنها کاری که باید انجام بشه اینه که تابعی نوشته بشه و به عنوان آرگومان به تابع ‍‍

پاس داده بشه. این تابع بایستی چهارتا ورودی داشته باشه که به ترتیبت ‍‍

هستن و نوع، مقدار، فرمت خروجی و متادیتاهاست. همین من با استفاده از همین‌‌ها فیلترم رو توسعه دادم و گذاشتم روی گیت‌هاب که اگه دیگران هم خواستن ازش استفاده کنن.

همین!
پ.ن.: برای مطالعه بیشتر به اینجا مراجعه کنید.

Markdown Doc Generation

markdown فرمت مورد علاقه تولید محتوای این روزهای من

اینم یه تجربه پراکنده دیگه!

من معمولا محتواهای زیادی تولید می‌کنم. یعنی گزارش پروژه، مستند‌سازی و … انجام میدم. معمولا قبلا برای این‌کار از word و office استفاده می‌کردم. بزرگترین مشکلی که با این سیستم داشتم این بود که به علت اینکه سیستم عامل اصلیم لینوکسه مجبور بودم توی یک ماشین مجازی کار کنم که به علت سرعت کم هارد دیسک لپ تاپم معمولا اذیتم می‌کرد. اما اخیرا یه مستند تقریبا ۷۰ صفحه‌ای با استفاده از markdown نوشتم که من رو به این نتیجه رسوند که الان وقت مهاجرت از ورد رسیده

قبلا نوشته بودم که چطور میشه یه متن رو یه بار نوشت و به فرمت‌های مختلف اون رو داشت. حالا من به کمک pandoc و markdown و latex و xepersian تونستم یه مجموعه ابزار کامل برای تبدیل متن با سر و شکل قابل قبول و قابل ارائه ایجاد کنم. حالا تصمیم گرفتم که این کار رو ادامه بدم و مشکلاتی که ممکنه بر بخورم رو اینجا مستند کنم.

همین!

چرا لینوکس را دوست دارم: داشتن نسخه latex و html مستندات

اینم یه تجربه پراکنده دیگه!

من به شخصه مدت‌هاست علاقه مندم که مستنداتی که تولید میکنم رو با نرم افزار latex بنویسم اما به هزاران دلیل، که مهم‌ترین عدم توانایی به اشتراک گذاری این فایل‌ها با دیگران(اکثر آدم‌هایی که من باهاشون کار میکنم) نتونستم این ایده رو اجرایی کنم. اما همیشه این علاقه در من وجود داشته و داره. به همین خاطر علمم رو در این زمینه زیاد میکنم. همچنین از وقتی که وبلاگ مینویسم به پست‌های وبلاگم به شکل یک مستند نگاه میکنم و دوست دارم اونها در فرمت لاتک داشته باشم.پس به این نتیجه رسیدم که بگردم و ببینم آیا روشی وجود داره که من مستندات رو به یه فرمت خاص بنویسم و بعدش به html و  فرمت لاتک تبدیل کنم؟

در ابتدای کار شواهدی پیدا کردم که احتمالا این روش وجود داره. اگه با روش مستند سازی doxygen آشنا باشید، مستندات با استفاده از فرمت خاص doxyegen نوشته میشن و این نرم افزار میتونه نتیجه رو به فرمت لاتک و html تبدیل کنه. پس کار امکان پذیره. همچنین یکی دیگه از نیازمندی‌های این راه‌حل برای تبدیل آسون بودنه تا مهاجرت و استفاده از راه حل کم هزینه باشه. همچنین به نظر من نوشتن به فرمت لاتک و html سخته و خیلی «تو دل برو» یا همون user friendly نیست. پس باید این نکته رو هم در پیدا کردن راه حل در نظر بگیرم.

خب حالا برم سراغ راه حلی که برای این مساله پیدا کردم. من از قبل با دو روش ساده نوشتن html که عبارتند از makrdown و reStructuredText بصورت محدودی آشنا بودم و میدونستم که تبدیل این فرمت‌های به html مثل آب خوردن انجام میشه پس نصف مساله حل بود. از اونجایی که من با markdown بیشتر آشنا بودم این زبان ساده شده رو انتخاب کردم. حالا میمونه تبدیل markdown به لاتک که بعد از یه ذره گشتن رسیدم به این دوتا پست(لینک، لینک) و با استفاده از اونها تونستم markdown رو به کمک ابزاری به نام pandoc به لاتک تبدیل کنم و با استفاده از زیپرشین اون رو تبدیل کنم به pdf. حالا مراحل انجام این کار رو اینجا مینویسم

  1. نوشتن مستند به فرمت markdown مثلا
    قسمت اول
    ======================
    
    نیازمندیها
    ======================
    پکیجهای زیر باید نصب شود
    
    ۱٫ پکیج اول
    ۲٫ پکیج اول
    ۳٫ پکیج اول
    
    ۴٫ پکیج اول
    ۵٫ پکیج اول
    
    ۶٫ سلام
    	۱٫ سلام ۲
    	۲٫ سلام ۳
    	۳٫ سلام ۴
    	۴٫ سلام ۵
    	۵٫ سلام ۶
    	۶٫ سلام ۷
    	۷٫ سلام ۸
    	۸٫ سلام ۹
    
    چطور کامپایل کنیم
    ====================
    کامپایل کن دیگه
    
  2. تبدیل این متن به فرمت xelatex با دستور زیر
    pandoc -f markdown --latex-engine=xelatex -R -i a.md -o a.tex
  3. متن نتیجه شده به شکل زیره که اضافاتی داره
    \section{قسمت اول}\label{ux642ux633ux645ux62a-ux627ux648ux644}
    
    \section{نیازمندیها}\label{ux646ux6ccux627ux632ux645ux646ux62fux6ccux647ux627}
    
    پکیجهای زیر باید نصب شود
    
    \begin{enumerate}[<+->]
    \def\labelenumi{\arabic{enumi}.}
    \item
      پکیج اول
    \item
      پکیج اول
    \item
      پکیج اول
    \item
      پکیج اول
    \item
      پکیج اول
    \item
      سلام
    
      \begin{enumerate}[<+->]
      \def\labelenumii{\arabic{enumii}.}
      \itemsep1pt\parskip0pt\parsep0pt
      \item
        سلام ۲
      \item
        سلام ۳
      \item
        سلام ۴
      \item
        سلام ۵
      \item
        سلام ۶
      \item
        سلام ۷
      \item
        سلام ۸
      \item
        سلام ۹
      \end{enumerate}
    \end{enumerate}
    
    \section{چطور کامپایل
    کنیم}\label{ux686ux637ux648ux631-ux6a9ux627ux645ux67eux627ux6ccux644-ux6a9ux646ux6ccux645}
    
    کامپایل کن دیگه
  4. حذف این اضافات با دستورارت زیر
    sed -i.bak 's/\[<+->\]//' a.tex
    sed -i.bak 's/\\def\\labelenumi{\\arabic{enumi}.}//g' a.tex
    sed -i.bak 's/\\itemsep1pt\\parskip0pt\\parsep0pt//g' a.tex
  5. که نتیجه میشه این
    \section{قسمت اول}\label{ux642ux633ux645ux62a-ux627ux648ux644}
    
    \section{نیازمندیها}\label{ux646ux6ccux627ux632ux645ux646ux62fux6ccux647ux627}
    
    پکیجهای زیر باید نصب شود
    
    \begin{enumerate}
    \item
      پکیج اول
    \item
      پکیج اول
    \item
      پکیج اول
    \item
      پکیج اول
    \item
      پکیج اول
    \item
      سلام
    
      \begin{enumerate}
      \item
        سلام ۲
      \item
        سلام ۳
      \item
        سلام ۴
      \item
        سلام ۵
      \item
        سلام ۶
      \item
        سلام ۷
      \item
        سلام ۸
      \item
        سلام ۹
      \end{enumerate}
    \end{enumerate}
    
    \section{چطور کامپایل
    کنیم}\label{ux686ux637ux648ux631-ux6a9ux627ux645ux67eux627ux6ccux644-ux6a9ux646ux6ccux645}
    
    کامپایل کن دیگه
  6. این متن به تنهایی توسط لاتک کامپایل نمیشه و باید یه سری تگ‌های استاندارد لاتک بهش اضافه بشه تا بگه فرمت مستند چیه فونتا چین و از این دست چیزا. بهترین راه برای انجام اینکار داشتن یه فایل دیگه برای اون تگ‌های و include کردن این فایل در اون فایل هست. یه نمونه از اون فایل به این صورته:
    \documentclass[a4paper,12pt]{book}
    \usepackage{aut_test}
    \usepackage[colorlinks,linkcolor=black,citecolor=black]{hyperref}
    \usepackage{graphicx}
    \usepackage{amsthm,amssymb}
    \usepackage{tocbibind}
    \usepackage{listings}
    \usepackage{xepersian}
    \settextfont[Scale=1]{B Zar}
    
    \begin{document}
    \chapter{فصل اول}
    \include{a}
    \end{document}
  7. و با این دستور لاتک رو کامپایل میکنیم
    xelatex  -synctex=-1 doc.tex
  8. و نتیجه توی اینجا قابل مشاهده است.

همین!