2015-04-25 2 views
3

Прошу прощения за такой вопрос. Но я действительно новичок в Haskell. Я обыскал Интернет целый день, но не нашел никакого примера.Как использовать фильтр Pandoc в Hakyll?

У меня есть фильтр pandoc, написанный на python (tikzcd.py). Я хочу использовать этот фильтр для обработки сообщений в блоге.

Я думаю, мне нужно использовать unixFilter или pandocCompileWithTransform, но мои знания для Haskell действительно недостаточны, чтобы найти решение самостоятельно.

Итак, может ли кто-нибудь предоставить мне пример?

----------- U - P - D - A - T - E - S ---------------

@ Майкл дает решение, используя pandocCompileWithTransformM и unixFilter. Оно работает. Но есть проблема.

При использовании фильтра из командной строки, что я буду делать это

pandoc -t json -READEROPTIONS input.markdown | ./filter.py | pandoc -f JSON -WRITEROPTIONS -o output.html 

или, что эквивалентно

pandoc --filter ./filter.py -READEROPTIONS -WRITEROPTIONS -o html 

Эта команда короче, но это не делает показать процедуры.

Но с pandocCompilerTransformM, он делает что-то вроде

pandoc -t html -READEROPTIONS -WRITEROPTIONS input.mardown | pandoc -t JSON | ./filter.py | pandoc -f JSON -WRITEROPTIONS -o output.html 

Разница в том, что текст, который передается filter.py отличается: одно содержимое непосредственно производится из уценки, в то время как другой это некоторые тексты, созданные из HTML, созданные из уценки. Как вы знаете, конвертировать что-то взад и вперед всегда вызовет непредсказуемую проблему. Поэтому я думаю, что может быть лучшее решение.

PS. Я уставился на изучение Хаскелла. Надеюсь, я смогу самостоятельно решить эту проблему. Спасибо!

ответ

3

В конце концов, я думаю, вы использовали бы оба. Используя это https://github.com/listx/listx_blog/blob/master/blog.hs в качестве модели, следующая форма будет иметь ту же форму, что и transformer has in it. transformer используется на lines 69-80 for 'posts', то есть в качестве третьего аргумента pandocCompilerWithTransformM, который является (Pandoc -> Compiler Pandoc) Здесь вам нужно будет добавить абсолютный путь к вашему фильтру python - или имя, если оно находится в $ PATH, и параметры чтения и записи (напримерdefaultHakyllReaderOptions и defaultHakyllWriterOptions)

import Text.Pandoc 
import Hakyll 

type Script = String 

transformer 
    :: Script   -- e.g. "/absolute/path/filter.py" 
    -> ReaderOptions -- e.g. defaultHakyllReaderOptions 
    -> WriterOptions -- e.g. defaultHakyllWriterOptions 
    -> (Pandoc -> Compiler Pandoc) 
transformer script reader_opts writer_opts pandoc = 
    do let input_json = writeJSON writer_opts pandoc 
     output_json <- unixFilter script [] input_json 
     return $ 
      -- either (error.show) id $ -- this line needs to be uncommented atm. 
      readJSON reader_opts output_json 

так же, (transformer "/usr/local/bin/myfilter.py" defaultHakyllReaderOptions defaultHakyllWriterOptions) может использоваться там, где (return . pandocTransform) используется в строке 125 этого example gist


Для отладки вы можете аутсорсинг все, чтобы unixFilter:

transform :: Script -> String -> Compiler String 
transform script md = do json0 <- unixFilter pandoc input_args md 
         json1 <- unixFilter script [] json0 
         unixFilter pandoc output_args json1 
where 
    pandoc = "pandoc" 
    input_args = words "-f markdown -t json" -- add others 
    output_args = words "-f json -t html" -- add others 

Три строки do являются эквивалентами этапов соединения unix в pandoc -t json | filter.py | pandoc -f json с любыми дополнительными аргументами.


Я думаю, что, возможно, вы правы, здесь есть дополнительный слой pandoc. Функции pandocCompilerWithTransform(M) предназначены для прямой функции Pandoc-> Pandoc - она ​​будет применена к Pandoc hakyll. Я думаю, нам следует отказаться от этого и напрямую использовать библиотеки Pandoc. Возможно использование unixCompile.

transformXLVI :: Script -> ReaderOptions -> WriterOptions -> String -> Compiler Html 
transformXLVI script ropts wopts = fmap fromJSON . unixFilter script [] . toJSON 
    where 
    toJSON = writeJSON wopts 
    --   . either (error . show) id -- for pandoc > 1.14 
       . readMarkdown ropts 
    fromJSON = writeHtml wopts 
    --   . either (error . show) id 
       . readJSON ropts 

Я надеюсь, что принципы выйдут из этих вариантов! Это должно быть почти таким же, как и предыдущие transform; мы используем библиотеку pandoc вместо вызовов в исполняемый файл pandoc.

+0

Большое спасибо за ваш ответ. Но у меня все еще есть вопрос. Если я правильно понял, ваше решение делает что-то вроде 'pandoc | pandoc -t json | ./filter.py | pandoc -f json'Pandoc дважды (Markdown ---> HTML ---> JSON ---> JSON ---> HTML) перед фильтром, результат немного отличается от результата 'pandoc -t | ./filter.py | pandoc -f json' (Markdown ---> JSON ---> JSON ---> HTML), посмотрев внешний вывод pandoc. Тем не менее, я мог немного изменить свой фильтр, чтобы получить желаемый результат. Еще раз спасибо. –

+0

Ой, подождите, я подумал, что вы используете hakyll, который сам будет обрабатывать эти вещи, используя библиотеки pandoc haskell, а не используя исполняемый файл 'pandoc'. Я в любом случае представлял себе «md -> json -> json -> html», где python выполняет бит 'json -> json' - это то, что делает скрипт. Если вы делаете html вручную с помощью исполняемого файла 'pandoc', то, как вы говорите, просто сделайте' cat myfile.md | pandoc -t json | ./filter.py | pandoc -f json -t html -s' (используя '-s' для автономного html). – Michael

+0

Верно, что процесс hakyll, который я описывал, преобразует уценку в «собственное» представление pandoc, затем перейдите к json, затем перечитайте измененный python json в собственное представление pandoc, а затем в html. Однако собственное представление haskell в стиле «Pandoc» практически не отличается от json, который ваш фильтр читает и записывает. Если бы у вас был фильтр, написанный в haskell, конечно, он мог бы пропустить json-шаг, который был бы использован для фильтра python. – Michael

Смежные вопросы